Skip to content
getdate.c 55.8 KiB
Newer Older
  tmp = (struct tm *)localtime_r(&Start, &keeptime);
Daniel Stenberg's avatar
Daniel Stenberg committed
  tmp = localtime (&Start);
Daniel Stenberg's avatar
Daniel Stenberg committed
  if (!tmp)
    return -1;
Daniel Stenberg's avatar
Daniel Stenberg committed
  cookie.yyYear = tmp->tm_year + TM_YEAR_ORIGIN;
  cookie.yyMonth = tmp->tm_mon + 1;
  cookie.yyDay = tmp->tm_mday;
  cookie.yyHour = tmp->tm_hour;
  cookie.yyMinutes = tmp->tm_min;
  cookie.yySeconds = tmp->tm_sec;
Daniel Stenberg's avatar
Daniel Stenberg committed
  tm.tm_isdst = tmp->tm_isdst;
Daniel Stenberg's avatar
Daniel Stenberg committed
  cookie.yyMeridian = MER24;
  cookie.yyRelSeconds = 0;
  cookie.yyRelMinutes = 0;
  cookie.yyRelHour = 0;
  cookie.yyRelDay = 0;
  cookie.yyRelMonth = 0;
  cookie.yyRelYear = 0;
  cookie.yyHaveDate = 0;
  cookie.yyHaveDay = 0;
  cookie.yyHaveRel = 0;
  cookie.yyHaveTime = 0;
  cookie.yyHaveZone = 0;

  if (yyparse (&cookie)
      || cookie.yyHaveTime > 1 || cookie.yyHaveZone > 1 ||
      cookie.yyHaveDate > 1 || cookie.yyHaveDay > 1)
Daniel Stenberg's avatar
Daniel Stenberg committed
    return -1;

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

  /* Let mktime deduce tm_isdst if we have an absolute timestamp,
     or if the relative timestamp mentions days, months, or years.  */
Daniel Stenberg's avatar
Daniel Stenberg committed
  if (cookie.yyHaveDate | cookie.yyHaveDay | cookie.yyHaveTime |
      cookie.yyRelDay | cookie.yyRelMonth | cookie.yyRelYear)
Daniel Stenberg's avatar
Daniel Stenberg committed
    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.  */
Daniel Stenberg's avatar
Daniel Stenberg committed
      if (cookie.yyHaveZone)
Daniel Stenberg's avatar
Daniel Stenberg committed
	{
	  tm = tm0;
	  if (tm.tm_year <= EPOCH - TM_YEAR_ORIGIN)
	    {
	      tm.tm_mday++;
Daniel Stenberg's avatar
Daniel Stenberg committed
	      cookie.yyTimezone -= 24 * 60;
Daniel Stenberg's avatar
Daniel Stenberg committed
	    }
	  else
	    {
	      tm.tm_mday--;
Daniel Stenberg's avatar
Daniel Stenberg committed
	      cookie.yyTimezone += 24 * 60;
Daniel Stenberg's avatar
Daniel Stenberg committed
	    }
	  Start = mktime (&tm);
	}

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

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

Daniel Stenberg's avatar
Daniel Stenberg committed
  if (cookie.yyHaveZone)
Daniel Stenberg's avatar
Daniel Stenberg committed
    {
      long delta;
      struct tm *gmt = gmtime (&Start);
      if (!gmt)
	return -1;
Daniel Stenberg's avatar
Daniel Stenberg committed
      delta = cookie.yyTimezone * 60L + difftm (&tm, gmt);
Daniel Stenberg's avatar
Daniel Stenberg committed
      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) */