⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mktime.c

📁 简单的时间处理类 希望有帮助 谢谢 简单的时间处理类 希望有帮助 谢谢
💻 C
📖 第 1 页 / 共 2 页
字号:
  /* Invert CONVERT by probing.  First assume the same offset as last     time.  */  t0 = ydhms_diff (year, yday, hour, min, sec,		   EPOCH_YEAR - TM_YEAR_BASE, 0, 0, 0, - guessed_offset);  if (TIME_T_MAX / INT_MAX / 366 / 24 / 60 / 60 < 3)    {      /* time_t isn't large enough to rule out overflows, so check	 for major overflows.  A gross check suffices, since if t0	 has overflowed, it is off by a multiple of TIME_T_MAX -	 TIME_T_MIN + 1.  So ignore any component of the difference	 that is bounded by a small value.  */      /* Approximate log base 2 of the number of time units per	 biennium.  A biennium is 2 years; use this unit instead of	 years to avoid integer overflow.  For example, 2 average	 Gregorian years are 2 * 365.2425 * 24 * 60 * 60 seconds,	 which is 63113904 seconds, and rint (log2 (63113904)) is	 26.  */      int ALOG2_SECONDS_PER_BIENNIUM = 26;      int ALOG2_MINUTES_PER_BIENNIUM = 20;      int ALOG2_HOURS_PER_BIENNIUM = 14;      int ALOG2_DAYS_PER_BIENNIUM = 10;      int LOG2_YEARS_PER_BIENNIUM = 1;      int approx_requested_biennia =	(SHR (year_requested, LOG2_YEARS_PER_BIENNIUM)	 - SHR (EPOCH_YEAR - TM_YEAR_BASE, LOG2_YEARS_PER_BIENNIUM)	 + SHR (mday, ALOG2_DAYS_PER_BIENNIUM)	 + SHR (hour, ALOG2_HOURS_PER_BIENNIUM)	 + SHR (min, ALOG2_MINUTES_PER_BIENNIUM)	 + (LEAP_SECONDS_POSSIBLE	    ? 0	    : SHR (sec, ALOG2_SECONDS_PER_BIENNIUM)));      int approx_biennia = SHR (t0, ALOG2_SECONDS_PER_BIENNIUM);      int diff = approx_biennia - approx_requested_biennia;      int abs_diff = diff < 0 ? - diff : diff;      /* IRIX 4.0.5 cc miscaculates TIME_T_MIN / 3: it erroneously	 gives a positive value of 715827882.  Setting a variable	 first then doing math on it seems to work.	 (ghazi@caip.rutgers.edu) */      time_t time_t_max = TIME_T_MAX;      time_t time_t_min = TIME_T_MIN;      time_t overflow_threshold =	(time_t_max / 3 - time_t_min / 3) >> ALOG2_SECONDS_PER_BIENNIUM;      if (overflow_threshold < abs_diff)	{	  /* Overflow occurred.  Try repairing it; this might work if	     the time zone offset is enough to undo the overflow.  */	  time_t repaired_t0 = -1 - t0;	  approx_biennia = SHR (repaired_t0, ALOG2_SECONDS_PER_BIENNIUM);	  diff = approx_biennia - approx_requested_biennia;	  abs_diff = diff < 0 ? - diff : diff;	  if (overflow_threshold < abs_diff)	    return -1;	  guessed_offset += repaired_t0 - t0;	  t0 = repaired_t0;	}    }  /* Repeatedly use the error to improve the guess.  */  for (t = t1 = t2 = t0, dst2 = 0;       (gt = guess_time_tm (year, yday, hour, min, sec, &t,			    ranged_convert (convert, &t, &tm)),	t != gt);       t1 = t2, t2 = t, t = gt, dst2 = tm.tm_isdst != 0)    if (t == t1 && t != t2	&& (tm.tm_isdst < 0	    || (isdst < 0		? dst2 <= (tm.tm_isdst != 0)		: (isdst != 0) != (tm.tm_isdst != 0))))      /* We can't possibly find a match, as we are oscillating	 between two values.  The requested time probably falls	 within a spring-forward gap of size GT - T.  Follow the common	 practice in this case, which is to return a time that is GT - T	 away from the requested time, preferring a time whose	 tm_isdst differs from the requested value.  (If no tm_isdst	 was requested and only one of the two values has a nonzero	 tm_isdst, prefer that value.)  In practice, this is more	 useful than returning -1.  */      goto offset_found;    else if (--remaining_probes == 0)      return -1;  /* We have a match.  Check whether tm.tm_isdst has the requested     value, if any.  */  if (isdst != tm.tm_isdst && 0 <= isdst && 0 <= tm.tm_isdst)    {      /* tm.tm_isdst has the wrong value.  Look for a neighboring	 time with the right value, and use its UTC offset.	 Heuristic: probe the adjacent timestamps in both directions,	 looking for the desired isdst.  This should work for all real	 time zone histories in the tz database.  */      /* Distance between probes when looking for a DST boundary.  In	 tzdata2003a, the shortest period of DST is 601200 seconds	 (e.g., America/Recife starting 2000-10-08 01:00), and the	 shortest period of non-DST surrounded by DST is 694800	 seconds (Africa/Tunis starting 1943-04-17 01:00).  Use the	 minimum of these two values, so we don't miss these short	 periods when probing.  */      int stride = 601200;      /* The longest period of DST in tzdata2003a is 536454000 seconds	 (e.g., America/Jujuy starting 1946-10-01 01:00).  The longest	 period of non-DST is much longer, but it makes no real sense	 to search for more than a year of non-DST, so use the DST	 max.  */      int duration_max = 536454000;      /* Search in both directions, so the maximum distance is half	 the duration; add the stride to avoid off-by-1 problems.  */      int delta_bound = duration_max / 2 + stride;      int delta, direction;      for (delta = stride; delta < delta_bound; delta += stride)	for (direction = -1; direction <= 1; direction += 2)	  {	    time_t ot = t + delta * direction;	    if ((ot < t) == (direction < 0))	      {		struct tm otm;		ranged_convert (convert, &ot, &otm);		if (otm.tm_isdst == isdst)		  {		    /* We found the desired tm_isdst.		       Extrapolate back to the desired time.  */		    t = guess_time_tm (year, yday, hour, min, sec, &ot, &otm);		    ranged_convert (convert, &t, &tm);		    goto offset_found;		  }	      }	  }    } offset_found:  *offset = guessed_offset + t - t0;  if (LEAP_SECONDS_POSSIBLE && sec_requested != tm.tm_sec)    {      /* Adjust time to reflect the tm_sec requested, not the normalized value.	 Also, repair any damage from a false match due to a leap second.  */      int sec_adjustment = (sec == 0 && tm.tm_sec == 60) - sec;      t1 = t + sec_requested;      t2 = t1 + sec_adjustment;      if (((t1 < t) != (sec_requested < 0))	  | ((t2 < t1) != (sec_adjustment < 0))	  | ! convert (&t2, &tm))	return -1;      t = t2;    }  *tp = tm;  return t;}/* FIXME: This should use a signed type wide enough to hold any UTC   offset in seconds.  'int' should be good enough for GNU code.  We   can't fix this unilaterally though, as other modules invoke   __mktime_internal.  */static time_t localtime_offset;/* Convert *TP to a time_t value.  */time_tmktime (struct tm *tp){#ifdef _LIBC  /* POSIX.1 8.1.1 requires that whenever mktime() is called, the     time zone names contained in the external variable `tzname' shall     be set as if the tzset() function had been called.  */  __tzset ();#endif  return __mktime_internal (tp, __localtime_r, &localtime_offset);}#ifdef weak_aliasweak_alias (mktime, timelocal)#endif#ifdef _LIBClibc_hidden_def (mktime)libc_hidden_weak (timelocal)#endif#if DEBUGstatic intnot_equal_tm (const struct tm *a, const struct tm *b){  return ((a->tm_sec ^ b->tm_sec)	  | (a->tm_min ^ b->tm_min)	  | (a->tm_hour ^ b->tm_hour)	  | (a->tm_mday ^ b->tm_mday)	  | (a->tm_mon ^ b->tm_mon)	  | (a->tm_year ^ b->tm_year)	  | (a->tm_yday ^ b->tm_yday)	  | (a->tm_isdst ^ b->tm_isdst));}static voidprint_tm (const struct tm *tp){  if (tp)    printf ("%04d-%02d-%02d %02d:%02d:%02d yday %03d wday %d isdst %d",	    tp->tm_year + TM_YEAR_BASE, tp->tm_mon + 1, tp->tm_mday,	    tp->tm_hour, tp->tm_min, tp->tm_sec,	    tp->tm_yday, tp->tm_wday, tp->tm_isdst);  else    printf ("0");}static intcheck_result (time_t tk, struct tm tmk, time_t tl, const struct tm *lt){  if (tk != tl || !lt || not_equal_tm (&tmk, lt))    {      printf ("mktime (");      print_tm (lt);      printf (")\nyields (");      print_tm (&tmk);      printf (") == %ld, should be %ld\n", (long int) tk, (long int) tl);      return 1;    }  return 0;}intmain (int argc, char **argv){  int status = 0;  struct tm tm, tmk, tml;  struct tm *lt;  time_t tk, tl, tl1;  char trailer;  if ((argc == 3 || argc == 4)      && (sscanf (argv[1], "%d-%d-%d%c",		  &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &trailer)	  == 3)      && (sscanf (argv[2], "%d:%d:%d%c",		  &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &trailer)	  == 3))    {      tm.tm_year -= TM_YEAR_BASE;      tm.tm_mon--;      tm.tm_isdst = argc == 3 ? -1 : atoi (argv[3]);      tmk = tm;      tl = mktime (&tmk);      lt = localtime (&tl);      if (lt)	{	  tml = *lt;	  lt = &tml;	}      printf ("mktime returns %ld == ", (long int) tl);      print_tm (&tmk);      printf ("\n");      status = check_result (tl, tmk, tl, lt);    }  else if (argc == 4 || (argc == 5 && strcmp (argv[4], "-") == 0))    {      time_t from = atol (argv[1]);      time_t by = atol (argv[2]);      time_t to = atol (argv[3]);      if (argc == 4)	for (tl = from; by < 0 ? to <= tl : tl <= to; tl = tl1)	  {	    lt = localtime (&tl);	    if (lt)	      {		tmk = tml = *lt;		tk = mktime (&tmk);		status |= check_result (tk, tmk, tl, &tml);	      }	    else	      {		printf ("localtime (%ld) yields 0\n", (long int) tl);		status = 1;	      }	    tl1 = tl + by;	    if ((tl1 < tl) != (by < 0))	      break;	  }      else	for (tl = from; by < 0 ? to <= tl : tl <= to; tl = tl1)	  {	    /* Null benchmark.  */	    lt = localtime (&tl);	    if (lt)	      {		tmk = tml = *lt;		tk = tl;		status |= check_result (tk, tmk, tl, &tml);	      }	    else	      {		printf ("localtime (%ld) yields 0\n", (long int) tl);		status = 1;	      }	    tl1 = tl + by;	    if ((tl1 < tl) != (by < 0))	      break;	  }    }  else    printf ("Usage:\\t%s YYYY-MM-DD HH:MM:SS [ISDST] # Test given time.\n\\t%s FROM BY TO # Test values FROM, FROM+BY, ..., TO.\n\\t%s FROM BY TO - # Do not test those values (for benchmark).\n",	    argv[0], argv[0], argv[0]);  return status;}#endif /* DEBUG *//*Local Variables:compile-command: "gcc -DDEBUG -Wall -W -O -g mktime.c -o mktime"End:*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -