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

📄 mktime.c

📁 简单的时间处理类 希望有帮助 谢谢 简单的时间处理类 希望有帮助 谢谢
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Convert a `struct tm' to a time_t value.   Copyright (C) 1993-1999, 2002-2005, 2006 Free Software Foundation, Inc.   This file is part of the GNU C Library.   Contributed by Paul Eggert <eggert@twinsun.com>.   The GNU C Library is free software; you can redistribute it and/or   modify it under the terms of the GNU Lesser General Public   License as published by the Free Software Foundation; either   version 2.1 of the License, or (at your option) any later version.   The GNU C Library is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   Lesser General Public License for more details.   You should have received a copy of the GNU Lesser General Public   License along with the GNU C Library; if not, write to the Free   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA   02111-1307 USA.  *//* Define this to have a standalone program to test this implementation of   mktime.  *//* #define DEBUG 1 */#ifdef HAVE_CONFIG_H# include <config.h>#endif/* Assume that leap seconds are possible, unless told otherwise.   If the host has a `zic' command with a `-L leapsecondfilename' option,   then it supports leap seconds; otherwise it probably doesn't.  */#ifndef LEAP_SECONDS_POSSIBLE# define LEAP_SECONDS_POSSIBLE 1#endif#include <sys/types.h>		/* Some systems define `time_t' here.  */#include <time.h>#include <limits.h>#include <string.h>		/* For the real memcpy prototype.  */#if DEBUG# include <stdio.h># include <stdlib.h>/* Make it work even if the system's libc has its own mktime routine.  */# define mktime my_mktime#endif /* DEBUG *//* Shift A right by B bits portably, by dividing A by 2**B and   truncating towards minus infinity.  A and B should be free of side   effects, and B should be in the range 0 <= B <= INT_BITS - 2, where   INT_BITS is the number of useful bits in an int.  GNU code can   assume that INT_BITS is at least 32.   ISO C99 says that A >> B is implementation-defined if A < 0.  Some   implementations (e.g., UNICOS 9.0 on a Cray Y-MP EL) don't shift   right in the usual way when A < 0, so SHR falls back on division if   ordinary A >> B doesn't seem to be the usual signed shift.  */#define SHR(a, b)	\  (-1 >> 1 == -1	\   ? (a) >> (b)		\   : (a) / (1 << (b)) - ((a) % (1 << (b)) < 0))/* The extra casts in the following macros work around compiler bugs,   e.g., in Cray C 5.0.3.0.  *//* True if the arithmetic type T is an integer type.  bool counts as   an integer.  */#define TYPE_IS_INTEGER(t) ((t) 1.5 == 1)/* True if negative values of the signed integer type T use two's   complement, ones' complement, or signed magnitude representation,   respectively.  Much GNU code assumes two's complement, but some   people like to be portable to all possible C hosts.  */#define TYPE_TWOS_COMPLEMENT(t) ((t) ~ (t) 0 == (t) -1)#define TYPE_ONES_COMPLEMENT(t) ((t) ~ (t) 0 == 0)#define TYPE_SIGNED_MAGNITUDE(t) ((t) ~ (t) 0 < (t) -1)/* True if the arithmetic type T is signed.  */#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))/* The maximum and minimum values for the integer type T.  These   macros have undefined behavior if T is signed and has padding bits.   If this is a problem for you, please let us know how to fix it for   your host.  */#define TYPE_MINIMUM(t) \  ((t) (! TYPE_SIGNED (t) \	? (t) 0 \	: TYPE_SIGNED_MAGNITUDE (t) \	? ~ (t) 0 \	: ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1)))#define TYPE_MAXIMUM(t) \  ((t) (! TYPE_SIGNED (t) \	? (t) -1 \	: ~ (~ (t) 0 << (sizeof (t) * CHAR_BIT - 1))))#ifndef TIME_T_MIN# define TIME_T_MIN TYPE_MINIMUM (time_t)#endif#ifndef TIME_T_MAX# define TIME_T_MAX TYPE_MAXIMUM (time_t)#endif#define TIME_T_MIDPOINT (SHR (TIME_T_MIN + TIME_T_MAX, 1) + 1)/* Verify a requirement at compile-time (unlike assert, which is runtime).  */#define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; }verify (time_t_is_integer, TYPE_IS_INTEGER (time_t));verify (twos_complement_arithmetic, TYPE_TWOS_COMPLEMENT (int));/* The code also assumes that signed integer overflow silently wraps   around, but this assumption can't be stated without causing a   diagnostic on some hosts.  */#define EPOCH_YEAR 1970#define TM_YEAR_BASE 1900verify (base_year_is_a_multiple_of_100, TM_YEAR_BASE % 100 == 0);/* Return 1 if YEAR + TM_YEAR_BASE is a leap year.  */static inline intleapyear (long int year){  /* Don't add YEAR to TM_YEAR_BASE, as that might overflow.     Also, work even if YEAR is negative.  */  return    ((year & 3) == 0     && (year % 100 != 0	 || ((year / 100) & 3) == (- (TM_YEAR_BASE / 100) & 3)));}/* How many days come before each month (0-12).  */#ifndef _LIBCstatic#endifconst unsigned short int __mon_yday[2][13] =  {    /* Normal years.  */    { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },    /* Leap years.  */    { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }  };#ifndef _LIBC/* Portable standalone applications should supply a "time_r.h" that   declares a POSIX-compliant localtime_r, for the benefit of older   implementations that lack localtime_r or have a nonstandard one.   See the gnulib time_r module for one way to implement this.  */# include "time_r.h"# undef __localtime_r# define __localtime_r localtime_r# define __mktime_internal mktime_internal#endif/* Return an integer value measuring (YEAR1-YDAY1 HOUR1:MIN1:SEC1) -   (YEAR0-YDAY0 HOUR0:MIN0:SEC0) in seconds, assuming that the clocks   were not adjusted between the time stamps.   The YEAR values uses the same numbering as TP->tm_year.  Values   need not be in the usual range.  However, YEAR1 must not be less   than 2 * INT_MIN or greater than 2 * INT_MAX.   The result may overflow.  It is the caller's responsibility to   detect overflow.  */static inline time_tydhms_diff (long int year1, long int yday1, int hour1, int min1, int sec1,	    int year0, int yday0, int hour0, int min0, int sec0){  verify (C99_integer_division, -1 / 2 == 0);  verify (long_int_year_and_yday_are_wide_enough,	  INT_MAX <= LONG_MAX / 2 || TIME_T_MAX <= UINT_MAX);  /* Compute intervening leap days correctly even if year is negative.     Take care to avoid integer overflow here.  */  int a4 = SHR (year1, 2) + SHR (TM_YEAR_BASE, 2) - ! (year1 & 3);  int b4 = SHR (year0, 2) + SHR (TM_YEAR_BASE, 2) - ! (year0 & 3);  int a100 = a4 / 25 - (a4 % 25 < 0);  int b100 = b4 / 25 - (b4 % 25 < 0);  int a400 = SHR (a100, 2);  int b400 = SHR (b100, 2);  int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);  /* Compute the desired time in time_t precision.  Overflow might     occur here.  */  time_t tyear1 = year1;  time_t years = tyear1 - year0;  time_t days = 365 * years + yday1 - yday0 + intervening_leap_days;  time_t hours = 24 * days + hour1 - hour0;  time_t minutes = 60 * hours + min1 - min0;  time_t seconds = 60 * minutes + sec1 - sec0;  return seconds;}/* Return a time_t value corresponding to (YEAR-YDAY HOUR:MIN:SEC),   assuming that *T corresponds to *TP and that no clock adjustments   occurred between *TP and the desired time.   If TP is null, return a value not equal to *T; this avoids false matches.   If overflow occurs, yield the minimal or maximal value, except do not   yield a value equal to *T.  */static time_tguess_time_tm (long int year, long int yday, int hour, int min, int sec,	       const time_t *t, const struct tm *tp){  if (tp)    {      time_t d = ydhms_diff (year, yday, hour, min, sec,			     tp->tm_year, tp->tm_yday,			     tp->tm_hour, tp->tm_min, tp->tm_sec);      time_t t1 = *t + d;      if ((t1 < *t) == (TYPE_SIGNED (time_t) ? d < 0 : TIME_T_MAX / 2 < d))	return t1;    }  /* Overflow occurred one way or another.  Return the nearest result     that is actually in range, except don't report a zero difference     if the actual difference is nonzero, as that would cause a false     match; and don't oscillate between two values, as that would     confuse the spring-forward gap detector.  */  return (*t < TIME_T_MIDPOINT	  ? (*t <= TIME_T_MIN + 1 ? *t + 1 : TIME_T_MIN)	  : (TIME_T_MAX - 1 <= *t ? *t - 1 : TIME_T_MAX));}/* Use CONVERT to convert *T to a broken down time in *TP.   If *T is out of range for conversion, adjust it so that   it is the nearest in-range value and then convert that.  */static struct tm *ranged_convert (struct tm *(*convert) (const time_t *, struct tm *),		time_t *t, struct tm *tp){  struct tm *r = convert (t, tp);  if (!r && *t)    {      time_t bad = *t;      time_t ok = 0;      /* BAD is a known unconvertible time_t, and OK is a known good one.	 Use binary search to narrow the range between BAD and OK until	 they differ by 1.  */      while (bad != ok + (bad < 0 ? -1 : 1))	{	  time_t mid = *t = (bad < 0			     ? bad + ((ok - bad) >> 1)			     : ok + ((bad - ok) >> 1));	  r = convert (t, tp);	  if (r)	    ok = mid;	  else	    bad = mid;	}      if (!r && ok)	{	  /* The last conversion attempt failed;	     revert to the most recent successful attempt.  */	  *t = ok;	  r = convert (t, tp);	}    }  return r;}/* Convert *TP to a time_t value, inverting   the monotonic and mostly-unit-linear conversion function CONVERT.   Use *OFFSET to keep track of a guess at the offset of the result,   compared to what the result would be for UTC without leap seconds.   If *OFFSET's guess is correct, only one CONVERT call is needed.   This function is external because it is used also by timegm.c.  */time_t__mktime_internal (struct tm *tp,		   struct tm *(*convert) (const time_t *, struct tm *),		   time_t *offset){  time_t t, gt, t0, t1, t2;  struct tm tm;  /* The maximum number of probes (calls to CONVERT) should be enough     to handle any combinations of time zone rule changes, solar time,     leap seconds, and oscillations around a spring-forward gap.     POSIX.1 prohibits leap seconds, but some hosts have them anyway.  */  int remaining_probes = 6;  /* Time requested.  Copy it in case CONVERT modifies *TP; this can     occur if TP is localtime's returned value and CONVERT is localtime.  */  int sec = tp->tm_sec;  int min = tp->tm_min;  int hour = tp->tm_hour;  int mday = tp->tm_mday;  int mon = tp->tm_mon;  int year_requested = tp->tm_year;  int isdst = tp->tm_isdst;  /* 1 if the previous probe was DST.  */  int dst2;  /* Ensure that mon is in range, and set year accordingly.  */  int mon_remainder = mon % 12;  int negative_mon_remainder = mon_remainder < 0;  int mon_years = mon / 12 - negative_mon_remainder;  long int lyear_requested = year_requested;  long int year = lyear_requested + mon_years;  /* The other values need not be in range:     the remaining code handles minor overflows correctly,     assuming int and time_t arithmetic wraps around.     Major overflows are caught at the end.  */  /* Calculate day of year from year, month, and day of month.     The result need not be in range.  */  int mon_yday = ((__mon_yday[leapyear (year)]		   [mon_remainder + 12 * negative_mon_remainder])		  - 1);  long int lmday = mday;  long int yday = mon_yday + lmday;  time_t guessed_offset = *offset;  int sec_requested = sec;  if (LEAP_SECONDS_POSSIBLE)    {      /* Handle out-of-range seconds specially,	 since ydhms_tm_diff assumes every minute has 60 seconds.  */      if (sec < 0)	sec = 0;      if (59 < sec)	sec = 59;    }

⌨️ 快捷键说明

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