int main(void) { struct TM d; Time64_T time = 1202380093LL; d.tm_year = 90; while(d.tm_year < 800) { gmtime64_r(&time, &d); printf("%"PRId64" %d %d %d %d %d %"PRId64" %d %d %d\n", time, d.tm_sec, d.tm_min, d.tm_hour, d.tm_mday, d.tm_mon, (Year)d.tm_year, d.tm_wday, d.tm_yday, d.tm_isdst ); time += 60 * 60 * 11 + 1; } return(0); }
struct tm64 Time::get_tm() { time64_t seconds = seconds_; struct tm64 tm = {0}; if(Fixnum* off = try_as<Fixnum>(offset_)) { seconds += off->to_long_long(); gmtime64_r(&seconds, &tm); } else if(CBOOL(is_gmt_)) { gmtime64_r(&seconds, &tm); } else { tzset(); localtime64_r(&seconds, &tm); } return tm; }
DOMText* EppUtil::createTextNode( DOMDocument& doc, const time_t cal, bool dateOnly ) { char buf[128]; struct tm tmp; #if EPP_SUPPORT_UNSIGNED_TIME_T /* { */ long long t = (long long) ((unsigned int) cal); (void) gmtime64_r(&t, &tmp); #else /* EPP_SUPPORT_UNSIGNED_TIME_T */ /* } */ #if defined(win32) /* { */ struct tm * p = gmtime(&cal); tmp = *p; #else /* defined(win32) */ /* } { */ (void) gmtime_r(&cal, &tmp); #endif /* defined(win32) */ /* } */ #endif /* EPP_SUPPORT_UNSIGNED_TIME_T */ /* } */ const char * fmt = dateOnly ? "%Y-%m-%d" : "%Y-%m-%dT%H:%M:%S.0Z"; buf[0] = '\0'; (void) strftime(buf, sizeof(buf), fmt, &tmp); return doc.createTextNode(XS(buf)); }
time64_t pivotal_timestamp () { time_t t_classic = time (NULL); time64_t ltime; struct tm mytime = *gmtime (&t_classic); gmtime64_r(<ime, &mytime); return ltime; }
/* Date stuff */ static PyObject* datetime_from_millis(long long millis) { int microseconds = (millis % 1000) * 1000; Time64_T seconds = millis / 1000; struct TM timeinfo; gmtime64_r(&seconds, &timeinfo); return PyDateTime_FromDateAndTime(timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec, microseconds); }
void DateHolder::load(){ m_year=1970; m_month=1; m_day=1; const Time64_T t= m_datetime/1000; // number of seconds since beginning of the Unix Epoch. /* TL;DR The gmttime in standard libray on windows platform cannot represent the date before Unix Epoch. http://msdn.microsoft.com/en-us/library/0z9czt0w(v=vs.100).aspx """ Both the 32-bit and 64-bit versions of gmtime, mktime, mkgmtime, and localtime all use one tm structure per thread for the conversion. Each call to one of these functions destroys the result of any previous call. If timer represents a date before midnight, January 1, 1970, gmtime returns NULL. There is no error return. _gmtime64, which uses the __time64_t structure, enables dates to be expressed up through 23:59:59, December 31, 3000, UTC, whereas _gmtime32 only represent dates through 03:14:07 January 19, 2038, UTC. Midnight, January 1, 1970, is the lower bound of the date range for both of these functions. gmtime is an inline function that evaluates to _gmtime64 and time_t is equivalent to __time64_t unless _USE_32BIT_TIME_T is defined. """ An alternative could be boost date_time libraray. ``` #include <boost/date_time/posix_time/posix_time.hpp> using namespace boost::posix_time; ptime pt = from_time_t(t); struct tm d = to_tm(pt); ``` Howerver, boost date_time library still has year 2038 problem which is still not fixed. https://svn.boost.org/trac/boost/ticket/4543 One reason is that the library converts the 64-bit`time_t t` into `seconds` type to get posix time. But boost uses `long` to represent `seconds`, which is 4 bytes on windows platform, http://msdn.microsoft.com/en-us/library/s3f49ktz.aspx We eventually choose the third-party MIT-licensed library written with ANSI C. https://github.com/schwern/y2038 */ struct TM d; gmtime64_r(&t,&d); m_year=1900 + static_cast<int32_t>(d.tm_year); m_month=d.tm_mon + 1; m_day=d.tm_mday; }
void DateTimeHolder::load(){ m_year=1970; m_month=1; m_day=1; m_hr=0; m_min=0; m_sec=0; m_msec=0; const Time64_T t=m_datetime/1000; // number of seconds since beginning of the Unix Epoch. struct TM dt; gmtime64_r(&t,&dt); m_year=1900 + dt.tm_year; m_month=dt.tm_mon + 1; m_day=dt.tm_mday; m_hr=dt.tm_hour; m_min=dt.tm_min; m_sec=dt.tm_sec; m_msec=m_datetime%1000; }
struct tm64* localtime64_r(const time64_t* time64, struct tm64* tm64) { if(*time64 >= LONG_MIN && *time64 <= LONG_MAX) { struct tm tm; memset(&tm, 0, sizeof(tm)); time_t time = (time_t) *time64; if(localtime_r(&time, &tm)) { tm_to_tm64(&tm, tm64); #ifndef HAVE_TM_ZONE #if HAVE_TZNAME && HAVE_DAYLIGHT tm64->tm_zone = tzname[daylight && tm64->tm_isdst]; #else tm64->tm_zone = NULL; #endif #endif return tm64; } } /* * First determine the (approximate) year that this timestamp * is in using the gmtime64_r function. We then use this so * we are able to map this to a year that should be compatible * with the system localtime_r */ struct tm64 gm; gmtime64_r(time64, &gm); int64_t gm_year = gm.tm_year; if(gm_year < 1902) { /* For years below the 32 bit size time_t value we need to use * the lower comparable years */ int day = day_of_week(gm_year, gm.tm_mon + 1, gm.tm_mday); if(gm.tm_mon == 2 && leap_year(gm_year)) { gm.tm_year = lower_leap_month_table[day]; } else { gm.tm_year = lower_common_month_table[gm.tm_mon][day]; } } else if(gm_year > 2037) { /* For years above the 32 bit size time_t value we need to use * the lower comparable years */ int day = day_of_week(gm_year, gm.tm_mon + 1, gm.tm_mday); if(gm.tm_mon == 2 && leap_year(gm_year)) { gm.tm_year = higher_leap_month_table[day]; } else { gm.tm_year = higher_common_month_table[gm.tm_mon][day]; } } /* * Get the timestamp for the safe date that we mapped the * large date to. */ time_t time = (time_t)timegm64(&gm); struct tm tm; memset(&tm, 0, sizeof(tm)); localtime_r(&time, &tm); tm_to_tm64(&tm, tm64); tm64->tm_year = gm_year; /* * We need to correct here for the case where the timezone difference * results in the dates occuring in two different years. */ int month_diff = tm64->tm_mon - gm.tm_mon; if(month_diff == 11) { tm64->tm_year--; } else if(month_diff == -11) { tm64->tm_year++; } /* If the gm year is a leap year, but the local isn't and we're on * December 31st in the local year, this is marked as day 365 because * the gm year is a leap year. Therefore we need to substract 1. */ if(!leap_year(tm64->tm_year) && tm64->tm_yday == 365 ) { tm64->tm_yday--; } #ifndef HAVE_TM_ZONE #if HAVE_TZNAME && HAVE_DAYLIGHT tm64->tm_zone = tzname[daylight && tm64->tm_isdst]; #else tm64->tm_zone = NULL; #endif #endif return tm64; }
struct TM *gmtime64(const Time64_T *time) { return gmtime64_r(time, &Static_Return_Date); }
struct TM *localtime64_r (const Time64_T *time, struct TM *local_tm) { time_t safe_time; struct tm safe_date; struct TM gm_tm; Year orig_year; int month_diff; assert(local_tm != NULL); /* Use the system localtime() if time_t is small enough */ if( SHOULD_USE_SYSTEM_LOCALTIME(*time) ) { safe_time = *time; TRACE1("Using system localtime for %lld\n", *time); LOCALTIME_R(&safe_time, &safe_date); copy_tm_to_TM(&safe_date, local_tm); assert(check_tm(local_tm)); return local_tm; } if( gmtime64_r(time, &gm_tm) == NULL ) { TRACE1("gmtime64_r returned null for %lld\n", *time); return NULL; } orig_year = gm_tm.tm_year; if (gm_tm.tm_year > (2037 - 1900) || gm_tm.tm_year < (1970 - 1900) ) { TRACE1("Mapping tm_year %lld to safe_year\n", (Year)gm_tm.tm_year); gm_tm.tm_year = safe_year((Year)(gm_tm.tm_year + 1900)) - 1900; } safe_time = timegm64(&gm_tm); if( LOCALTIME_R(&safe_time, &safe_date) == NULL ) { TRACE1("localtime_r(%d) returned NULL\n", (int)safe_time); return NULL; } copy_tm_to_TM(&safe_date, local_tm); local_tm->tm_year = orig_year; if( local_tm->tm_year != orig_year ) { TRACE2("tm_year overflow: tm_year %lld, orig_year %lld\n", (Year)local_tm->tm_year, (Year)orig_year); #ifdef EOVERFLOW errno = EOVERFLOW; #endif return NULL; } month_diff = local_tm->tm_mon - gm_tm.tm_mon; /* When localtime is Dec 31st previous year and gmtime is Jan 1st next year. */ if( month_diff == 11 ) { local_tm->tm_year--; } /* When localtime is Jan 1st, next year and gmtime is Dec 31st, previous year. */ if( month_diff == -11 ) { local_tm->tm_year++; } /* GMT is Jan 1st, xx01 year, but localtime is still Dec 31st in a non-leap xx00. There is one point in the cycle we can't account for which the safe xx00 year is a leap year. So we need to correct for Dec 31st comming out as the 366th day of the year. */ if( !IS_LEAP(local_tm->tm_year) && local_tm->tm_yday == 365 ) local_tm->tm_yday--; assert(check_tm(local_tm)); return local_tm; }