| #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 | |