1864c0d50cda714d73fa70e3600ec36b5db8a835aMathias Agopian#include "TimeUtils.h"
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdio.h>
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <cutils/tztime.h>
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android {
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectdump(const Time& t)
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    #ifdef HAVE_TM_GMTOFF
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long tm_gmtoff = t.t.tm_gmtoff;
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    #else
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long tm_gmtoff = 0;
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    #endif
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    printf("%04d-%02d-%02d %02d:%02d:%02d (%d,%ld,%d,%d)\n",
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            t.t.tm_year+1900, t.t.tm_mon+1, t.t.tm_mday,
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            t.t.tm_hour, t.t.tm_min, t.t.tm_sec,
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            t.t.tm_isdst, tm_gmtoff, t.t.tm_wday, t.t.tm_yday);
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectTime::Time()
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    t.tm_sec = 0;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    t.tm_min = 0;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    t.tm_hour = 0;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    t.tm_mday = 0;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    t.tm_mon = 0;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    t.tm_year = 0;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    t.tm_wday = 0;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    t.tm_yday = 0;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    t.tm_isdst = -1; // we don't know, so let the C library determine
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    #ifdef HAVE_TM_GMTOFF
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        t.tm_gmtoff = 0;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    #endif
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define COMPARE_FIELD(field) do { \
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int diff = a.t.field - b.t.field; \
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (diff != 0) return diff; \
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } while(0)
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectTime::compare(Time& a, Time& b)
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (0 == strcmp(a.timezone, b.timezone)) {
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // if the timezones are the same, we can easily compare the two
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // times.  Otherwise, convert to milliseconds and compare that.
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // This requires that object be normalized.
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        COMPARE_FIELD(tm_year);
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        COMPARE_FIELD(tm_mon);
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        COMPARE_FIELD(tm_mday);
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        COMPARE_FIELD(tm_hour);
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        COMPARE_FIELD(tm_min);
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        COMPARE_FIELD(tm_sec);
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 0;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int64_t am = a.toMillis(false /* use isDst */);
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int64_t bm = b.toMillis(false /* use isDst */);
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int64_t diff = am-bm;
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return (diff < 0) ? -1 : ((diff > 0) ? 1 : 0);
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic const int DAYS_PER_MONTH[] = {
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    };
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic inline int days_this_month(int year, int month)
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int n = DAYS_PER_MONTH[month];
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (n != 28) {
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return n;
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int y = year;
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return ((y%4)==0&&((y%100)!=0||(y%400)==0)) ? 29 : 28;
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectTime::switchTimezone(const char* timezone)
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    time_t seconds = mktime_tz(&(this->t), this->timezone);
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    localtime_tz(&seconds, &(this->t), timezone);
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectString8
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectTime::format(const char *format, const struct strftime_locale *locale) const
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    char buf[257];
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int n = strftime_tz(buf, 257, format, &(this->t), locale);
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (n > 0) {
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return String8(buf);
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return String8();
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic inline short
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projecttochar(int n)
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return (n >= 0 && n <= 9) ? ('0'+n) : ' ';
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic inline short
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnext_char(int *m, int k)
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int n = *m / k;
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    *m = *m % k;
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return tochar(n);
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectTime::format2445(short* buf, bool hasTime) const
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int n;
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    n = t.tm_year+1900;
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    buf[0] = next_char(&n, 1000);
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    buf[1] = next_char(&n, 100);
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    buf[2] = next_char(&n, 10);
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    buf[3] = tochar(n);
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    n = t.tm_mon+1;
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    buf[4] = next_char(&n, 10);
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    buf[5] = tochar(n);
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    n = t.tm_mday;
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    buf[6] = next_char(&n, 10);
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    buf[7] = tochar(n);
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (hasTime) {
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      buf[8] = 'T';
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      n = t.tm_hour;
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      buf[9] = next_char(&n, 10);
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      buf[10] = tochar(n);
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      n = t.tm_min;
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      buf[11] = next_char(&n, 10);
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      buf[12] = tochar(n);
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      n = t.tm_sec;
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      buf[13] = next_char(&n, 10);
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      buf[14] = tochar(n);
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      bool inUtc = strcmp("UTC", timezone) == 0;
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      if (inUtc) {
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project          buf[15] = 'Z';
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      }
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectString8
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectTime::toString() const
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String8 str;
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    char* s = str.lockBuffer(150);
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    #ifdef HAVE_TM_GMTOFF
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long tm_gmtoff = t.tm_gmtoff;
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    #else
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long tm_gmtoff = 0;
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    #endif
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sprintf(s, "%04d%02d%02dT%02d%02d%02d%s(%d,%d,%ld,%d,%d)",
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            t.tm_year+1900, t.tm_mon+1, t.tm_mday, t.tm_hour, t.tm_min,
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            t.tm_sec, timezone, t.tm_wday, t.tm_yday, tm_gmtoff, t.tm_isdst,
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (int)(((Time*)this)->toMillis(false /* use isDst */)/1000));
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    str.unlockBuffer();
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return str;
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectTime::setToNow()
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    time_t seconds;
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    time(&seconds);
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    localtime_tz(&seconds, &(this->t), this->timezone);
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint64_t
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectTime::toMillis(bool ignoreDst)
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (ignoreDst) {
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this->t.tm_isdst = -1;
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int64_t r = mktime_tz(&(this->t), this->timezone);
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (r == -1)
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return r * 1000;
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectTime::set(int64_t millis)
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    time_t seconds = millis / 1000;
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    localtime_tz(&seconds, &(this->t), this->timezone);
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; // namespace android
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
200