• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "TimeUtils.h"
2 #include <stdio.h>
3 #include <cutils/tztime.h>
4 
5 namespace android {
6 
7 static void
dump(const Time & t)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 
Time()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
compare(Time & a,Time & b)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 
days_this_month(int year,int month)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
switchTimezone(const char * timezone)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
format(const char * format,const struct strftime_locale * locale) const88 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
tochar(int n)100 tochar(int n)
101 {
102     return (n >= 0 && n <= 9) ? ('0'+n) : ' ';
103 }
104 
105 static inline short
next_char(int * m,int k)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
format2445(short * buf,bool hasTime) const114 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
toString() const154 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
setToNow()172 Time::setToNow()
173 {
174     time_t seconds;
175     time(&seconds);
176     localtime_tz(&seconds, &(this->t), this->timezone);
177 }
178 
179 int64_t
toMillis(bool ignoreDst)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
set(int64_t millis)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