#include "TimeUtils.h" #include <stdio.h> #include <cutils/tztime.h> namespace android { static void dump(const Time& t) { #ifdef HAVE_TM_GMTOFF long tm_gmtoff = t.t.tm_gmtoff; #else long tm_gmtoff = 0; #endif printf("%04d-%02d-%02d %02d:%02d:%02d (%d,%ld,%d,%d)\n", t.t.tm_year+1900, t.t.tm_mon+1, t.t.tm_mday, t.t.tm_hour, t.t.tm_min, t.t.tm_sec, t.t.tm_isdst, tm_gmtoff, t.t.tm_wday, t.t.tm_yday); } Time::Time() { t.tm_sec = 0; t.tm_min = 0; t.tm_hour = 0; t.tm_mday = 0; t.tm_mon = 0; t.tm_year = 0; t.tm_wday = 0; t.tm_yday = 0; t.tm_isdst = -1; // we don't know, so let the C library determine #ifdef HAVE_TM_GMTOFF t.tm_gmtoff = 0; #endif } #define COMPARE_FIELD(field) do { \ int diff = a.t.field - b.t.field; \ if (diff != 0) return diff; \ } while(0) int Time::compare(Time& a, Time& b) { if (0 == strcmp(a.timezone, b.timezone)) { // if the timezones are the same, we can easily compare the two // times. Otherwise, convert to milliseconds and compare that. // This requires that object be normalized. COMPARE_FIELD(tm_year); COMPARE_FIELD(tm_mon); COMPARE_FIELD(tm_mday); COMPARE_FIELD(tm_hour); COMPARE_FIELD(tm_min); COMPARE_FIELD(tm_sec); return 0; } else { int64_t am = a.toMillis(false /* use isDst */); int64_t bm = b.toMillis(false /* use isDst */); int64_t diff = am-bm; return (diff < 0) ? -1 : ((diff > 0) ? 1 : 0); } } static const int DAYS_PER_MONTH[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; static inline int days_this_month(int year, int month) { int n = DAYS_PER_MONTH[month]; if (n != 28) { return n; } else { int y = year; return ((y%4)==0&&((y%100)!=0||(y%400)==0)) ? 29 : 28; } } void Time::switchTimezone(const char* timezone) { time_t seconds = mktime_tz(&(this->t), this->timezone); localtime_tz(&seconds, &(this->t), timezone); } String8 Time::format(const char *format, const struct strftime_locale *locale) const { char buf[257]; int n = strftime_tz(buf, 257, format, &(this->t), locale); if (n > 0) { return String8(buf); } else { return String8(); } } static inline short tochar(int n) { return (n >= 0 && n <= 9) ? ('0'+n) : ' '; } static inline short next_char(int *m, int k) { int n = *m / k; *m = *m % k; return tochar(n); } void Time::format2445(short* buf, bool hasTime) const { int n; n = t.tm_year+1900; buf[0] = next_char(&n, 1000); buf[1] = next_char(&n, 100); buf[2] = next_char(&n, 10); buf[3] = tochar(n); n = t.tm_mon+1; buf[4] = next_char(&n, 10); buf[5] = tochar(n); n = t.tm_mday; buf[6] = next_char(&n, 10); buf[7] = tochar(n); if (hasTime) { buf[8] = 'T'; n = t.tm_hour; buf[9] = next_char(&n, 10); buf[10] = tochar(n); n = t.tm_min; buf[11] = next_char(&n, 10); buf[12] = tochar(n); n = t.tm_sec; buf[13] = next_char(&n, 10); buf[14] = tochar(n); bool inUtc = strcmp("UTC", timezone) == 0; if (inUtc) { buf[15] = 'Z'; } } } String8 Time::toString() const { String8 str; char* s = str.lockBuffer(150); #ifdef HAVE_TM_GMTOFF long tm_gmtoff = t.tm_gmtoff; #else long tm_gmtoff = 0; #endif sprintf(s, "%04d%02d%02dT%02d%02d%02d%s(%d,%d,%ld,%d,%d)", t.tm_year+1900, t.tm_mon+1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, timezone, t.tm_wday, t.tm_yday, tm_gmtoff, t.tm_isdst, (int)(((Time*)this)->toMillis(false /* use isDst */)/1000)); str.unlockBuffer(); return str; } void Time::setToNow() { time_t seconds; time(&seconds); localtime_tz(&seconds, &(this->t), this->timezone); } int64_t Time::toMillis(bool ignoreDst) { if (ignoreDst) { this->t.tm_isdst = -1; } int64_t r = mktime_tz(&(this->t), this->timezone); if (r == -1) return -1; return r * 1000; } void Time::set(int64_t millis) { time_t seconds = millis / 1000; localtime_tz(&seconds, &(this->t), this->timezone); } }; // namespace android