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