1 #include "TimeUtils.h" 2 #include <stdio.h> 3 #include <cutils/tztime.h> 4 5 namespace android { 6 7 static void 8 dump(const Time& t) 9 { 10 #ifdef HAVE_TM_GMTOFF 11 long tm_gmtoff = t.t.tm_gmtoff; 12 #else 13 long tm_gmtoff = 0; 14 #endif 15 printf("%04d-%02d-%02d %02d:%02d:%02d (%d,%ld,%d,%d)\n", 16 t.t.tm_year+1900, t.t.tm_mon+1, t.t.tm_mday, 17 t.t.tm_hour, t.t.tm_min, t.t.tm_sec, 18 t.t.tm_isdst, tm_gmtoff, t.t.tm_wday, t.t.tm_yday); 19 } 20 21 Time::Time() 22 { 23 t.tm_sec = 0; 24 t.tm_min = 0; 25 t.tm_hour = 0; 26 t.tm_mday = 0; 27 t.tm_mon = 0; 28 t.tm_year = 0; 29 t.tm_wday = 0; 30 t.tm_yday = 0; 31 t.tm_isdst = -1; // we don't know, so let the C library determine 32 #ifdef HAVE_TM_GMTOFF 33 t.tm_gmtoff = 0; 34 #endif 35 } 36 37 38 #define COMPARE_FIELD(field) do { \ 39 int diff = a.t.field - b.t.field; \ 40 if (diff != 0) return diff; \ 41 } while(0) 42 43 int 44 Time::compare(Time& a, Time& b) 45 { 46 if (0 == strcmp(a.timezone, b.timezone)) { 47 // if the timezones are the same, we can easily compare the two 48 // times. Otherwise, convert to milliseconds and compare that. 49 // This requires that object be normalized. 50 COMPARE_FIELD(tm_year); 51 COMPARE_FIELD(tm_mon); 52 COMPARE_FIELD(tm_mday); 53 COMPARE_FIELD(tm_hour); 54 COMPARE_FIELD(tm_min); 55 COMPARE_FIELD(tm_sec); 56 return 0; 57 } else { 58 int64_t am = a.toMillis(false /* use isDst */); 59 int64_t bm = b.toMillis(false /* use isDst */); 60 int64_t diff = am-bm; 61 return (diff < 0) ? -1 : ((diff > 0) ? 1 : 0); 62 } 63 } 64 65 static const int DAYS_PER_MONTH[] = { 66 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 67 }; 68 69 static inline int days_this_month(int year, int month) 70 { 71 int n = DAYS_PER_MONTH[month]; 72 if (n != 28) { 73 return n; 74 } else { 75 int y = year; 76 return ((y%4)==0&&((y%100)!=0||(y%400)==0)) ? 29 : 28; 77 } 78 } 79 80 void 81 Time::switchTimezone(const char* timezone) 82 { 83 time_t seconds = mktime_tz(&(this->t), this->timezone); 84 localtime_tz(&seconds, &(this->t), timezone); 85 } 86 87 String8 88 Time::format(const char *format, const struct strftime_locale *locale) const 89 { 90 char buf[257]; 91 int n = strftime_tz(buf, 257, format, &(this->t), locale); 92 if (n > 0) { 93 return String8(buf); 94 } else { 95 return String8(); 96 } 97 } 98 99 static inline short 100 tochar(int n) 101 { 102 return (n >= 0 && n <= 9) ? ('0'+n) : ' '; 103 } 104 105 static inline short 106 next_char(int *m, int k) 107 { 108 int n = *m / k; 109 *m = *m % k; 110 return tochar(n); 111 } 112 113 void 114 Time::format2445(short* buf, bool hasTime) const 115 { 116 int n; 117 118 n = t.tm_year+1900; 119 buf[0] = next_char(&n, 1000); 120 buf[1] = next_char(&n, 100); 121 buf[2] = next_char(&n, 10); 122 buf[3] = tochar(n); 123 124 n = t.tm_mon+1; 125 buf[4] = next_char(&n, 10); 126 buf[5] = tochar(n); 127 128 n = t.tm_mday; 129 buf[6] = next_char(&n, 10); 130 buf[7] = tochar(n); 131 132 if (hasTime) { 133 buf[8] = 'T'; 134 135 n = t.tm_hour; 136 buf[9] = next_char(&n, 10); 137 buf[10] = tochar(n); 138 139 n = t.tm_min; 140 buf[11] = next_char(&n, 10); 141 buf[12] = tochar(n); 142 143 n = t.tm_sec; 144 buf[13] = next_char(&n, 10); 145 buf[14] = tochar(n); 146 bool inUtc = strcmp("UTC", timezone) == 0; 147 if (inUtc) { 148 buf[15] = 'Z'; 149 } 150 } 151 } 152 153 String8 154 Time::toString() const 155 { 156 String8 str; 157 char* s = str.lockBuffer(150); 158 #ifdef HAVE_TM_GMTOFF 159 long tm_gmtoff = t.tm_gmtoff; 160 #else 161 long tm_gmtoff = 0; 162 #endif 163 sprintf(s, "%04d%02d%02dT%02d%02d%02d%s(%d,%d,%ld,%d,%d)", 164 t.tm_year+1900, t.tm_mon+1, t.tm_mday, t.tm_hour, t.tm_min, 165 t.tm_sec, timezone, t.tm_wday, t.tm_yday, tm_gmtoff, t.tm_isdst, 166 (int)(((Time*)this)->toMillis(false /* use isDst */)/1000)); 167 str.unlockBuffer(); 168 return str; 169 } 170 171 void 172 Time::setToNow() 173 { 174 time_t seconds; 175 time(&seconds); 176 localtime_tz(&seconds, &(this->t), this->timezone); 177 } 178 179 int64_t 180 Time::toMillis(bool ignoreDst) 181 { 182 if (ignoreDst) { 183 this->t.tm_isdst = -1; 184 } 185 int64_t r = mktime_tz(&(this->t), this->timezone); 186 if (r == -1) 187 return -1; 188 return r * 1000; 189 } 190 191 void 192 Time::set(int64_t millis) 193 { 194 time_t seconds = millis / 1000; 195 localtime_tz(&seconds, &(this->t), this->timezone); 196 } 197 198 }; // namespace android 199 200