Skip to content
getdate.c 54.2 KiB
Newer Older
Daniel Stenberg's avatar
Daniel Stenberg committed
  yyRelSeconds = 0;
  yyRelMinutes = 0;
  yyRelHour = 0;
  yyRelDay = 0;
  yyRelMonth = 0;
  yyRelYear = 0;
  yyHaveDate = 0;
  yyHaveDay = 0;
  yyHaveRel = 0;
  yyHaveTime = 0;
  yyHaveZone = 0;

  if (yyparse ()
      || yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 || yyHaveDay > 1)
    return -1;

  tm.tm_year = ToYear (yyYear) - TM_YEAR_ORIGIN + yyRelYear;
  tm.tm_mon = yyMonth - 1 + yyRelMonth;
  tm.tm_mday = yyDay + yyRelDay;
  if (yyHaveTime || (yyHaveRel && !yyHaveDate && !yyHaveDay))
    {
      tm.tm_hour = ToHour (yyHour, yyMeridian);
      if (tm.tm_hour < 0)
	return -1;
      tm.tm_min = yyMinutes;
      tm.tm_sec = yySeconds;
    }
  else
    {
      tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
    }
  tm.tm_hour += yyRelHour;
  tm.tm_min += yyRelMinutes;
  tm.tm_sec += yyRelSeconds;

  /* Let mktime deduce tm_isdst if we have an absolute timestamp,
     or if the relative timestamp mentions days, months, or years.  */
  if (yyHaveDate | yyHaveDay | yyHaveTime | yyRelDay | yyRelMonth | yyRelYear)
    tm.tm_isdst = -1;

  tm0 = tm;

  Start = mktime (&tm);

  if (Start == (time_t) -1)
    {

      /* Guard against falsely reporting errors near the time_t boundaries
         when parsing times in other time zones.  For example, if the min
         time_t value is 1970-01-01 00:00:00 UTC and we are 8 hours ahead
         of UTC, then the min localtime value is 1970-01-01 08:00:00; if
         we apply mktime to 1970-01-01 00:00:00 we will get an error, so
         we apply mktime to 1970-01-02 08:00:00 instead and adjust the time
         zone by 24 hours to compensate.  This algorithm assumes that
         there is no DST transition within a day of the time_t boundaries.  */
      if (yyHaveZone)
	{
	  tm = tm0;
	  if (tm.tm_year <= EPOCH - TM_YEAR_ORIGIN)
	    {
	      tm.tm_mday++;
	      yyTimezone -= 24 * 60;
	    }
	  else
	    {
	      tm.tm_mday--;
	      yyTimezone += 24 * 60;
	    }
	  Start = mktime (&tm);
	}

      if (Start == (time_t) -1)
	return Start;
    }

  if (yyHaveDay && !yyHaveDate)
    {
      tm.tm_mday += ((yyDayNumber - tm.tm_wday + 7) % 7
		     + 7 * (yyDayOrdinal - (0 < yyDayOrdinal)));
      Start = mktime (&tm);
      if (Start == (time_t) -1)
	return Start;
    }

  if (yyHaveZone)
    {
      long delta;
      struct tm *gmt = gmtime (&Start);
      if (!gmt)
	return -1;
      delta = yyTimezone * 60L + difftm (&tm, gmt);
      if ((Start + delta < Start) != (delta < 0))
	return -1;		/* time_t overflow */
      Start += delta;
    }

  return Start;
}

#if	defined (TEST)

/* ARGSUSED */
int
main (ac, av)
     int ac;
     char *av[];
{
  char buff[MAX_BUFF_LEN + 1];
  time_t d;

  (void) printf ("Enter date, or blank line to exit.\n\t> ");
  (void) fflush (stdout);

  buff[MAX_BUFF_LEN] = 0;
  while (fgets (buff, MAX_BUFF_LEN, stdin) && buff[0])
    {
      d = curl_getdate (buff, (time_t *) NULL);
Daniel Stenberg's avatar
Daniel Stenberg committed
      if (d == -1)
	(void) printf ("Bad format - couldn't convert.\n");
      else
	(void) printf ("%s", ctime (&d));
      (void) printf ("\t> ");
      (void) fflush (stdout);
    }
  exit (0);
  /* NOTREACHED */
}
#endif /* defined (TEST) */

/*
 * local variables:
 * eval: (load-file "../curl-mode.el")
 * end:
 * vim600: fdm=marker
 * vim: et sw=2 ts=2 sts=2 tw=78