11dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectCopyright (c) 2007-2008 Michael G Schwern 41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectThis software originally derived from Paul Sheer's pivotal_gmtime_r.c. 61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectThe MIT License: 81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectPermission is hereby granted, free of charge, to any person obtaining a copy 101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectof this software and associated documentation files (the "Software"), to deal 111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectin the Software without restriction, including without limitation the rights 121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectto use, copy, modify, merge, publish, distribute, sublicense, and/or sell 131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectcopies of the Software, and to permit persons to whom the Software is 141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectfurnished to do so, subject to the following conditions: 151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectThe above copyright notice and this permission notice shall be included in 171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectall copies or substantial portions of the Software. 181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectTHE SOFTWARE. 261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project*/ 281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* See http://code.google.com/p/y2038 for this code's origin */ 301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 318d77bce185d04c531bd9bf34d38e5cbbe644d3a3Elliott Hughes#if defined(__LP64__) 328d77bce185d04c531bd9bf34d38e5cbbe644d3a3Elliott Hughes#error This cruft should be LP32 only! 338d77bce185d04c531bd9bf34d38e5cbbe644d3a3Elliott Hughes#endif 348d77bce185d04c531bd9bf34d38e5cbbe644d3a3Elliott Hughes 351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectProgrammers who have available to them 64-bit time values as a 'long 381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectlong' type can use localtime64_r() and gmtime64_r() which correctly 391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectconverts the time even on 32-bit systems. Whether you have 64-bit time 401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectvalues will depend on the operating system. 411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectlocaltime64_r() is a 64-bit equivalent of localtime_r(). 431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectgmtime64_r() is a 64-bit equivalent of gmtime_r(). 451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project*/ 471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <assert.h> 491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdlib.h> 501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdio.h> 511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <string.h> 521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <time.h> 531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <errno.h> 541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "time64.h" 551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* BIONIC_BEGIN */ 571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* the following are here to avoid exposing time64_config.h and 581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * other types in our public time64.h header 591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "time64_config.h" 611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Not everyone has gm/localtime_r(), provide a replacement */ 631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef HAS_LOCALTIME_R 641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# define LOCALTIME_R(clock, result) localtime_r(clock, result) 651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else 661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# define LOCALTIME_R(clock, result) fake_localtime_r(clock, result) 671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef HAS_GMTIME_R 691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# define GMTIME_R(clock, result) gmtime_r(clock, result) 701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else 711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# define GMTIME_R(clock, result) fake_gmtime_r(clock, result) 721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projecttypedef int64_t Int64; 751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projecttypedef time64_t Time64_T; 761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projecttypedef int64_t Year; 771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define TM tm 781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* BIONIC_END */ 791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Spec says except for stftime() and the _r() functions, these 811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project all return static memory. Stabbings! */ 821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic struct TM Static_Return_Date; 831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic char Static_Return_String[35]; 841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const int days_in_month[2][12] = { 861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}; 891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const int julian_days_by_month[2][12] = { 911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}, 921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}, 931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}; 941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic char const wday_name[7][3] = { 961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" 971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}; 981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic char const mon_name[12][3] = { 1001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project "Jan", "Feb", "Mar", "Apr", "May", "Jun", 1011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 1021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}; 1031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const int length_of_year[2] = { 365, 366 }; 1051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Some numbers relating to the gregorian cycle */ 1071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const Year years_in_gregorian_cycle = 400; 1081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define days_in_gregorian_cycle ((365 * 400) + 100 - 4 + 1) 1091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const Time64_T seconds_in_gregorian_cycle = days_in_gregorian_cycle * 60LL * 60LL * 24LL; 1101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Year range we can trust the time funcitons with */ 1121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define MAX_SAFE_YEAR 2037 1131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define MIN_SAFE_YEAR 1971 1141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 28 year Julian calendar cycle */ 1161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define SOLAR_CYCLE_LENGTH 28 1171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Year cycle from MAX_SAFE_YEAR down. */ 1191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const int safe_years_high[SOLAR_CYCLE_LENGTH] = { 1201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2016, 2017, 2018, 2019, 1211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2020, 2021, 2022, 2023, 1221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2024, 2025, 2026, 2027, 1231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2028, 2029, 2030, 2031, 1241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2032, 2033, 2034, 2035, 1251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2036, 2037, 2010, 2011, 1261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2012, 2013, 2014, 2015 1271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}; 1281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Year cycle from MIN_SAFE_YEAR up */ 1301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const int safe_years_low[SOLAR_CYCLE_LENGTH] = { 1311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1996, 1997, 1998, 1971, 1321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1972, 1973, 1974, 1975, 1331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1976, 1977, 1978, 1979, 1341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1980, 1981, 1982, 1983, 1351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1984, 1985, 1986, 1987, 1361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1988, 1989, 1990, 1991, 1371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1992, 1993, 1994, 1995, 1381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}; 1391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Let's assume people are going to be looking for dates in the future. 1411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project Let's provide some cheats so you can skip ahead. 1421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project This has a 4x speed boost when near 2008. 1431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project*/ 1441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Number of days since epoch on Jan 1st, 2008 GMT */ 1451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define CHEAT_DAYS (1199145600 / 24 / 60 / 60) 1461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define CHEAT_YEARS 108 1471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define IS_LEAP(n) ((!(((n) + 1900) % 400) || (!(((n) + 1900) % 4) && (((n) + 1900) % 100))) != 0) 1491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define WRAP(a,b,m) ((a) = ((a) < 0 ) ? ((b)--, (a) + (m)) : (a)) 1501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef USE_SYSTEM_LOCALTIME 1521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# define SHOULD_USE_SYSTEM_LOCALTIME(a) ( \ 1531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (a) <= SYSTEM_LOCALTIME_MAX && \ 1541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (a) >= SYSTEM_LOCALTIME_MIN \ 1551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project) 1561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else 1571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# define SHOULD_USE_SYSTEM_LOCALTIME(a) (0) 1581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 1591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef USE_SYSTEM_GMTIME 1611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# define SHOULD_USE_SYSTEM_GMTIME(a) ( \ 1621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (a) <= SYSTEM_GMTIME_MAX && \ 1631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (a) >= SYSTEM_GMTIME_MIN \ 1641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project) 1651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else 1661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# define SHOULD_USE_SYSTEM_GMTIME(a) (0) 1671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 1681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Multi varadic macros are a C99 thing, alas */ 1701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef TIME_64_DEBUG 1711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# define TRACE(format) (fprintf(stderr, format)) 1721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# define TRACE1(format, var1) (fprintf(stderr, format, var1)) 1731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# define TRACE2(format, var1, var2) (fprintf(stderr, format, var1, var2)) 1741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# define TRACE3(format, var1, var2, var3) (fprintf(stderr, format, var1, var2, var3)) 1751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else 1761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# define TRACE(format) ((void)0) 1771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# define TRACE1(format, var1) ((void)0) 1781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# define TRACE2(format, var1, var2) ((void)0) 1791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# define TRACE3(format, var1, var2, var3) ((void)0) 1801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 1811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int is_exception_century(Year year) 1841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 1851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int is_exception = ((year % 100 == 0) && !(year % 400 == 0)); 1861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project TRACE1("# is_exception_century: %s\n", is_exception ? "yes" : "no"); 1871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(is_exception); 1891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 1901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* timegm() is not in the C or POSIX spec, but it is such a useful 1931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project extension I would be remiss in leaving it out. Also I need it 1941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for localtime64() 1951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project*/ 1961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectTime64_T timegm64(const struct TM *date) { 1971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project Time64_T days = 0; 1981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project Time64_T seconds = 0; 1991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project Year year; 2001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project Year orig_year = (Year)date->tm_year; 2011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int cycles = 0; 2021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if( orig_year > 100 ) { 2041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cycles = (orig_year - 100) / 400; 2051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project orig_year -= cycles * 400; 2061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project days += (Time64_T)cycles * days_in_gregorian_cycle; 2071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else if( orig_year < -300 ) { 2091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cycles = (orig_year - 100) / 400; 2101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project orig_year -= cycles * 400; 2111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project days += (Time64_T)cycles * days_in_gregorian_cycle; 2121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project TRACE3("# timegm/ cycles: %d, days: %lld, orig_year: %lld\n", cycles, days, orig_year); 2141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if( orig_year > 70 ) { 2161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project year = 70; 2171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while( year < orig_year ) { 2181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project days += length_of_year[IS_LEAP(year)]; 2191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project year++; 2201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else if ( orig_year < 70 ) { 2231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project year = 69; 2241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project do { 2251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project days -= length_of_year[IS_LEAP(year)]; 2261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project year--; 2271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } while( year >= orig_year ); 2281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project days += julian_days_by_month[IS_LEAP(orig_year)][date->tm_mon]; 2321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project days += date->tm_mday - 1; 2331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project seconds = days * 60 * 60 * 24; 2351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project seconds += date->tm_hour * 60 * 60; 2371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project seconds += date->tm_min * 60; 2381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project seconds += date->tm_sec; 2391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(seconds); 2411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 2421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 244066eb0b06d51e7ccbaea92e11de9c747314b03d6Elliott Hughes#if !defined(NDEBUG) 2451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int check_tm(struct TM *tm) 2461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 2471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Don't forget leap seconds */ 2481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(tm->tm_sec >= 0); 2491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(tm->tm_sec <= 61); 2501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(tm->tm_min >= 0); 2521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(tm->tm_min <= 59); 2531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(tm->tm_hour >= 0); 2551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(tm->tm_hour <= 23); 2561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(tm->tm_mday >= 1); 2581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(tm->tm_mday <= days_in_month[IS_LEAP(tm->tm_year)][tm->tm_mon]); 2591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(tm->tm_mon >= 0); 2611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(tm->tm_mon <= 11); 2621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(tm->tm_wday >= 0); 2641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(tm->tm_wday <= 6); 2658d77bce185d04c531bd9bf34d38e5cbbe644d3a3Elliott Hughes 2661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(tm->tm_yday >= 0); 2671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(tm->tm_yday <= length_of_year[IS_LEAP(tm->tm_year)]); 2681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef HAS_TM_TM_GMTOFF 2701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(tm->tm_gmtoff >= -24 * 60 * 60); 2711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(tm->tm_gmtoff <= 24 * 60 * 60); 2721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 2731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 1; 2751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 276066eb0b06d51e7ccbaea92e11de9c747314b03d6Elliott Hughes#endif 2771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* The exceptional centuries without leap years cause the cycle to 2801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project shift by 16 2811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project*/ 2821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic Year cycle_offset(Year year) 2831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 2841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const Year start_year = 2000; 2851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project Year year_diff = year - start_year; 2861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project Year exceptions; 2871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if( year > start_year ) 2891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project year_diff--; 2901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project exceptions = year_diff / 100; 2921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project exceptions -= year_diff / 400; 2931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project TRACE3("# year: %lld, exceptions: %lld, year_diff: %lld\n", 2951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project year, exceptions, year_diff); 2961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return exceptions * 16; 2981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 2991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* For a given year after 2038, pick the latest possible matching 3011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project year in the 28 year calendar cycle. 3021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project A matching year... 3041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1) Starts on the same day of the week. 3051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2) Has the same leap year status. 3061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project This is so the calendars match up. 3081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project Also the previous year must match. When doing Jan 1st you might 3101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project wind up on Dec 31st the previous year when doing a -UTC time zone. 3111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project Finally, the next year must have the same start day of week. This 3131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project is for Dec 31st with a +UTC time zone. 3141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project It doesn't need the same leap year status since we only care about 3151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project January 1st. 3161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project*/ 3171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int safe_year(const Year year) 3181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 3191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int safe_year = 0; 3201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project Year year_cycle; 3211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if( year >= MIN_SAFE_YEAR && year <= MAX_SAFE_YEAR ) { 3231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (int)year; 3241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project year_cycle = year + cycle_offset(year); 3271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* safe_years_low is off from safe_years_high by 8 years */ 3291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if( year < MIN_SAFE_YEAR ) 3301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project year_cycle -= 8; 3311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Change non-leap xx00 years to an equivalent */ 3331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if( is_exception_century(year) ) 3341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project year_cycle += 11; 3351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Also xx01 years, since the previous year will be wrong */ 3371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if( is_exception_century(year - 1) ) 3381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project year_cycle += 17; 3391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project year_cycle %= SOLAR_CYCLE_LENGTH; 3411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if( year_cycle < 0 ) 3421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project year_cycle = SOLAR_CYCLE_LENGTH + year_cycle; 3431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert( year_cycle >= 0 ); 3451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert( year_cycle < SOLAR_CYCLE_LENGTH ); 3461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if( year < MIN_SAFE_YEAR ) 3471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project safe_year = safe_years_low[year_cycle]; 3481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else if( year > MAX_SAFE_YEAR ) 3491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project safe_year = safe_years_high[year_cycle]; 3501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else 3511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(0); 3521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project TRACE3("# year: %lld, year_cycle: %lld, safe_year: %d\n", 3541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project year, year_cycle, safe_year); 3551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(safe_year <= MAX_SAFE_YEAR && safe_year >= MIN_SAFE_YEAR); 3571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return safe_year; 3591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 3601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3628b2707a6a074e64a36ced73b45f5c5fbe774b63bJim Huangstatic void copy_tm_to_TM(const struct tm *src, struct TM *dest) { 3631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if( src == NULL ) { 3641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memset(dest, 0, sizeof(*dest)); 3651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else { 3671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# ifdef USE_TM64 3681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dest->tm_sec = src->tm_sec; 3691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dest->tm_min = src->tm_min; 3701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dest->tm_hour = src->tm_hour; 3711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dest->tm_mday = src->tm_mday; 3721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dest->tm_mon = src->tm_mon; 3731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dest->tm_year = (Year)src->tm_year; 3741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dest->tm_wday = src->tm_wday; 3751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dest->tm_yday = src->tm_yday; 3761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dest->tm_isdst = src->tm_isdst; 3771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# ifdef HAS_TM_TM_GMTOFF 3791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dest->tm_gmtoff = src->tm_gmtoff; 3801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# endif 3811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# ifdef HAS_TM_TM_ZONE 3831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dest->tm_zone = src->tm_zone; 3841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# endif 3851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# else 3871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* They're the same type */ 3881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memcpy(dest, src, sizeof(*dest)); 3891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# endif 3901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 3921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3948b2707a6a074e64a36ced73b45f5c5fbe774b63bJim Huangstatic void copy_TM_to_tm(const struct TM *src, struct tm *dest) { 3951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if( src == NULL ) { 3961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memset(dest, 0, sizeof(*dest)); 3971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else { 3991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# ifdef USE_TM64 4001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dest->tm_sec = src->tm_sec; 4011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dest->tm_min = src->tm_min; 4021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dest->tm_hour = src->tm_hour; 4031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dest->tm_mday = src->tm_mday; 4041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dest->tm_mon = src->tm_mon; 4051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dest->tm_year = (int)src->tm_year; 4061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dest->tm_wday = src->tm_wday; 4071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dest->tm_yday = src->tm_yday; 4081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dest->tm_isdst = src->tm_isdst; 4091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# ifdef HAS_TM_TM_GMTOFF 4111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dest->tm_gmtoff = src->tm_gmtoff; 4121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# endif 4131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# ifdef HAS_TM_TM_ZONE 4151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dest->tm_zone = src->tm_zone; 4161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# endif 4171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# else 4191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* They're the same type */ 4201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memcpy(dest, src, sizeof(*dest)); 4211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# endif 4221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 4231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 4241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Simulate localtime_r() to the best of our ability */ 4271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstruct tm * fake_localtime_r(const time_t *clock, struct tm *result) { 4281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const struct tm *static_result = localtime(clock); 4291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(result != NULL); 4311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if( static_result == NULL ) { 4331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memset(result, 0, sizeof(*result)); 4341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NULL; 4351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 4361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else { 4371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memcpy(result, static_result, sizeof(*result)); 4381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return result; 4391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 4401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 4411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Simulate gmtime_r() to the best of our ability */ 4451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstruct tm * fake_gmtime_r(const time_t *clock, struct tm *result) { 4461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const struct tm *static_result = gmtime(clock); 4471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(result != NULL); 4491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if( static_result == NULL ) { 4511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memset(result, 0, sizeof(*result)); 4521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NULL; 4531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 4541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else { 4551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memcpy(result, static_result, sizeof(*result)); 4561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return result; 4571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 4581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 4591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic Time64_T seconds_between_years(Year left_year, Year right_year) { 4621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int increment = (left_year > right_year) ? 1 : -1; 4631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project Time64_T seconds = 0; 4641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int cycles; 4651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if( left_year > 2400 ) { 4671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cycles = (left_year - 2400) / 400; 4681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project left_year -= cycles * 400; 4691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project seconds += cycles * seconds_in_gregorian_cycle; 4701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 4711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else if( left_year < 1600 ) { 4721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cycles = (left_year - 1600) / 400; 4731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project left_year += cycles * 400; 4741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project seconds += cycles * seconds_in_gregorian_cycle; 4751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 4761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while( left_year != right_year ) { 4781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project seconds += length_of_year[IS_LEAP(right_year - 1900)] * 60 * 60 * 24; 4791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project right_year += increment; 4801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 4811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return seconds * increment; 4831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 4841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectTime64_T mktime64(const struct TM *input_date) { 4871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct tm safe_date; 4881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct TM date; 4891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project Time64_T time; 4901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project Year year = input_date->tm_year + 1900; 4911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if( MIN_SAFE_YEAR <= year && year <= MAX_SAFE_YEAR ) { 4931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project copy_TM_to_tm(input_date, &safe_date); 4941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (Time64_T)mktime(&safe_date); 4951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 4961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Have to make the year safe in date else it won't fit in safe_date */ 4981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project date = *input_date; 4991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project date.tm_year = safe_year(year) - 1900; 5001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project copy_TM_to_tm(&date, &safe_date); 5011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project time = (Time64_T)mktime(&safe_date); 5031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project time += seconds_between_years(year, (Year)(safe_date.tm_year + 1900)); 5051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return time; 5071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 5081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Because I think mktime() is a crappy name */ 5111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectTime64_T timelocal64(const struct TM *date) { 5121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return mktime64(date); 5131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 5141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstruct TM *gmtime64_r (const Time64_T *in_time, struct TM *p) 5171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 5181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int v_tm_sec, v_tm_min, v_tm_hour, v_tm_mon, v_tm_wday; 5191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project Time64_T v_tm_tday; 5201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int leap; 5211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project Time64_T m; 5221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project Time64_T time = *in_time; 5231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project Year year = 70; 5241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int cycles = 0; 5251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(p != NULL); 5271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Use the system gmtime() if time_t is small enough */ 5291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if( SHOULD_USE_SYSTEM_GMTIME(*in_time) ) { 5301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project time_t safe_time = *in_time; 5311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct tm safe_date; 5321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project GMTIME_R(&safe_time, &safe_date); 5331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project copy_tm_to_TM(&safe_date, p); 5351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(check_tm(p)); 5361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return p; 5381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 5391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef HAS_TM_TM_GMTOFF 5411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project p->tm_gmtoff = 0; 5421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 5431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project p->tm_isdst = 0; 5441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef HAS_TM_TM_ZONE 5461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project p->tm_zone = "UTC"; 5471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 5481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project v_tm_sec = (int)(time % 60); 5501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project time /= 60; 5511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project v_tm_min = (int)(time % 60); 5521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project time /= 60; 5531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project v_tm_hour = (int)(time % 24); 5541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project time /= 24; 5551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project v_tm_tday = time; 5561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project WRAP (v_tm_sec, v_tm_min, 60); 5581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project WRAP (v_tm_min, v_tm_hour, 60); 5591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project WRAP (v_tm_hour, v_tm_tday, 24); 5601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project v_tm_wday = (int)((v_tm_tday + 4) % 7); 5621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (v_tm_wday < 0) 5631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project v_tm_wday += 7; 5641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project m = v_tm_tday; 5651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (m >= CHEAT_DAYS) { 5671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project year = CHEAT_YEARS; 5681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project m -= CHEAT_DAYS; 5691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 5701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (m >= 0) { 5721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Gregorian cycles, this is huge optimization for distant times */ 5731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cycles = (int)(m / (Time64_T) days_in_gregorian_cycle); 5741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if( cycles ) { 5751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project m -= (cycles * (Time64_T) days_in_gregorian_cycle); 5761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project year += (cycles * years_in_gregorian_cycle); 5771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 5781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Years */ 5801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project leap = IS_LEAP (year); 5811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while (m >= (Time64_T) length_of_year[leap]) { 5821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project m -= (Time64_T) length_of_year[leap]; 5831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project year++; 5841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project leap = IS_LEAP (year); 5851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 5861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Months */ 5881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project v_tm_mon = 0; 5891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while (m >= (Time64_T) days_in_month[leap][v_tm_mon]) { 5901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project m -= (Time64_T) days_in_month[leap][v_tm_mon]; 5911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project v_tm_mon++; 5921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 5931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else { 5941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project year--; 5951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Gregorian cycles */ 5971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cycles = (int)((m / (Time64_T) days_in_gregorian_cycle) + 1); 5981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if( cycles ) { 5991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project m -= (cycles * (Time64_T) days_in_gregorian_cycle); 6001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project year += (cycles * years_in_gregorian_cycle); 6011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 6021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Years */ 6041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project leap = IS_LEAP (year); 6051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while (m < (Time64_T) -length_of_year[leap]) { 6061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project m += (Time64_T) length_of_year[leap]; 6071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project year--; 6081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project leap = IS_LEAP (year); 6091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 6101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Months */ 6121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project v_tm_mon = 11; 6131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while (m < (Time64_T) -days_in_month[leap][v_tm_mon]) { 6141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project m += (Time64_T) days_in_month[leap][v_tm_mon]; 6151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project v_tm_mon--; 6161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 6171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project m += (Time64_T) days_in_month[leap][v_tm_mon]; 6181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 6191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project p->tm_year = year; 6211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if( p->tm_year != year ) { 6221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef EOVERFLOW 6231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EOVERFLOW; 6241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 6251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NULL; 6261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 6271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* At this point m is less than a year so casting to an int is safe */ 6291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project p->tm_mday = (int) m + 1; 6301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project p->tm_yday = julian_days_by_month[leap][v_tm_mon] + (int)m; 6311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project p->tm_sec = v_tm_sec; 6321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project p->tm_min = v_tm_min; 6331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project p->tm_hour = v_tm_hour; 6341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project p->tm_mon = v_tm_mon; 6351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project p->tm_wday = v_tm_wday; 6361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(check_tm(p)); 6381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return p; 6401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 6411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstruct TM *localtime64_r (const Time64_T *time, struct TM *local_tm) 6441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 6451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project time_t safe_time; 6461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct tm safe_date; 6471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct TM gm_tm; 6481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project Year orig_year; 6491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int month_diff; 6501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(local_tm != NULL); 6521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Use the system localtime() if time_t is small enough */ 6541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if( SHOULD_USE_SYSTEM_LOCALTIME(*time) ) { 6551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project safe_time = *time; 6561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project TRACE1("Using system localtime for %lld\n", *time); 6581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project LOCALTIME_R(&safe_time, &safe_date); 6601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project copy_tm_to_TM(&safe_date, local_tm); 6621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(check_tm(local_tm)); 6631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return local_tm; 6651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 6661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if( gmtime64_r(time, &gm_tm) == NULL ) { 6681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project TRACE1("gmtime64_r returned null for %lld\n", *time); 6691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NULL; 6701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 6711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project orig_year = gm_tm.tm_year; 6731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (gm_tm.tm_year > (2037 - 1900) || 6751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project gm_tm.tm_year < (1970 - 1900) 6761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ) 6771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project { 6781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project TRACE1("Mapping tm_year %lld to safe_year\n", (Year)gm_tm.tm_year); 6791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project gm_tm.tm_year = safe_year((Year)(gm_tm.tm_year + 1900)) - 1900; 6801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 6811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project safe_time = timegm64(&gm_tm); 6831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if( LOCALTIME_R(&safe_time, &safe_date) == NULL ) { 6841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project TRACE1("localtime_r(%d) returned NULL\n", (int)safe_time); 6851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NULL; 6861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 6871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project copy_tm_to_TM(&safe_date, local_tm); 6891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project local_tm->tm_year = orig_year; 6911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if( local_tm->tm_year != orig_year ) { 6921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project TRACE2("tm_year overflow: tm_year %lld, orig_year %lld\n", 6931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (Year)local_tm->tm_year, (Year)orig_year); 6941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef EOVERFLOW 6961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EOVERFLOW; 6971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 6981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NULL; 6991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 7001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project month_diff = local_tm->tm_mon - gm_tm.tm_mon; 7031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* When localtime is Dec 31st previous year and 7051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project gmtime is Jan 1st next year. 7061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 7071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if( month_diff == 11 ) { 7081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project local_tm->tm_year--; 7091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 7101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* When localtime is Jan 1st, next year and 7121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project gmtime is Dec 31st, previous year. 7131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 7141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if( month_diff == -11 ) { 7151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project local_tm->tm_year++; 7161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 7171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* GMT is Jan 1st, xx01 year, but localtime is still Dec 31st 7191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project in a non-leap xx00. There is one point in the cycle 7201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project we can't account for which the safe xx00 year is a leap 7211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project year. So we need to correct for Dec 31st comming out as 7221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project the 366th day of the year. 7231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 7241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if( !IS_LEAP(local_tm->tm_year) && local_tm->tm_yday == 365 ) 7251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project local_tm->tm_yday--; 7261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(check_tm(local_tm)); 7281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return local_tm; 7301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 7311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7338b2707a6a074e64a36ced73b45f5c5fbe774b63bJim Huangstatic int valid_tm_wday( const struct TM* date ) { 7341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if( 0 <= date->tm_wday && date->tm_wday <= 6 ) 7351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 1; 7361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else 7371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 7381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 7391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7408b2707a6a074e64a36ced73b45f5c5fbe774b63bJim Huangstatic int valid_tm_mon( const struct TM* date ) { 7411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if( 0 <= date->tm_mon && date->tm_mon <= 11 ) 7421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 1; 7431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else 7441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 7451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 7461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectchar *asctime64_r( const struct TM* date, char *result ) { 7491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* I figure everything else can be displayed, even hour 25, but if 7501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project these are out of range we walk off the name arrays */ 7511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if( !valid_tm_wday(date) || !valid_tm_mon(date) ) 7521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NULL; 7531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project sprintf(result, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n", 7551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project wday_name[date->tm_wday], 7561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project mon_name[date->tm_mon], 7571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project date->tm_mday, date->tm_hour, 7581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project date->tm_min, date->tm_sec, 7591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1900 + date->tm_year); 7601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return result; 7621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 7631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectchar *ctime64_r( const Time64_T* time, char* result ) { 7661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct TM date; 7671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project localtime64_r( time, &date ); 7691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return asctime64_r( &date, result ); 7701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 7711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Non-thread safe versions of the above */ 7741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstruct TM *localtime64(const Time64_T *time) { 7751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return localtime64_r(time, &Static_Return_Date); 7761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 7771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstruct TM *gmtime64(const Time64_T *time) { 7791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return gmtime64_r(time, &Static_Return_Date); 7801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 7811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectchar *asctime64( const struct TM* date ) { 7831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return asctime64_r( date, Static_Return_String ); 7841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 7851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectchar *ctime64( const Time64_T* time ) { 7871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return asctime64(localtime64(time)); 7881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 789