Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(309)

Side by Side Diff: chrome/browser/sync/notifier/base/time.cc

Issue 194065: Initial commit of sync engine code to browser/sync.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Fixes to gtest include path, reverted syncapi. Created 11 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/sync/notifier/base/time.h"
6
7 #include <string>
8 #include <time.h>
9
10 #include "chrome/browser/sync/notifier/base/string.h"
11 #include "chrome/browser/sync/notifier/base/utils.h"
12 #include "talk/base/common.h"
13 #include "talk/base/logging.h"
14
15 namespace notifier {
16
17 // Get the current time represented in 100NS granularity since epoch
18 // (Jan 1, 1970)
19 time64 GetCurrent100NSTimeSinceEpoch() {
20 return GetCurrent100NSTime() - kStart100NsTimeToEpoch;
21 }
22
23 char* GetLocalTimeAsString() {
24 time64 long_time = GetCurrent100NSTime();
25 struct tm now;
26 Time64ToTm(long_time, &now);
27 char* time_string = asctime(&now);
28 if (time_string) {
29 int time_len = strlen(time_string);
30 if (time_len > 0) {
31 time_string[time_len - 1] = 0; // trim off terminating \n
32 }
33 }
34 return time_string;
35 }
36
37 // Parses RFC 822 Date/Time format
38 // 5. DATE AND TIME SPECIFICATION
39 // 5.1. SYNTAX
40 //
41 // date-time = [ day "," ] date time ; dd mm yy
42 // ; hh:mm:ss zzz
43 // day = "Mon" / "Tue" / "Wed" / "Thu"
44 // / "Fri" / "Sat" / "Sun"
45 //
46 // date = 1*2DIGIT month 2DIGIT ; day month year
47 // ; e.g. 20 Jun 82
48 //
49 // month = "Jan" / "Feb" / "Mar" / "Apr"
50 // / "May" / "Jun" / "Jul" / "Aug"
51 // / "Sep" / "Oct" / "Nov" / "Dec"
52 //
53 // time = hour zone ; ANSI and Military
54 //
55 // hour = 2DIGIT ":" 2DIGIT [":" 2DIGIT]
56 // ; 00:00:00 - 23:59:59
57 //
58 // zone = "UT" / "GMT" ; Universal Time
59 // ; North American : UT
60 // / "EST" / "EDT" ; Eastern: - 5/ - 4
61 // / "CST" / "CDT" ; Central: - 6/ - 5
62 // / "MST" / "MDT" ; Mountain: - 7/ - 6
63 // / "PST" / "PDT" ; Pacific: - 8/ - 7
64 // / 1ALPHA ; Military: Z = UT;
65 // ; A:-1; (J not used)
66 // ; M:-12; N:+1; Y:+12
67 // / ( ("+" / "-") 4DIGIT ) ; Local differential
68 // ; hours+min. (HHMM)
69 // Return local time if ret_local_time == true, return UTC time otherwise
70 const int kNumOfDays = 7;
71 const int kNumOfMonth = 12;
72 // Note: RFC822 does not include '-' as a separator, but Http Cookies use
73 // it in the date field, like this: Wdy, DD-Mon-YYYY HH:MM:SS GMT
74 // This differs from RFC822 only by those dashes. It is legacy quirk from
75 // old Netscape cookie specification. So it makes sense to expand this
76 // parser rather then add another one.
77 // See http://wp.netscape.com/newsref/std/cookie_spec.html
78 const char kRFC822_DateDelimiters[] = " ,:-";
79
80 const char kRFC822_TimeDelimiter[] = ": ";
81 const char* kRFC822_Day[] = {
82 "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"
83 };
84 const char* kRFC822_Month[] = {
85 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
86 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
87 };
88
89 struct TimeZoneInfo {
90 const char* zone_name;
91 int hour_dif;
92 };
93
94 const TimeZoneInfo kRFC822_TimeZone[] = {
95 { "UT", 0 },
96 { "GMT", 0 },
97 { "EST", -5 },
98 { "EDT", -4 },
99 { "CST", -6 },
100 { "CDT", -5 },
101 { "MST", -7 },
102 { "MDT", -6 },
103 { "PST", -8 },
104 { "PDT", -7 },
105 { "A", -1 }, // Military time zones
106 { "B", -2 },
107 { "C", -3 },
108 { "D", -4 },
109 { "E", -5 },
110 { "F", -6 },
111 { "G", -7 },
112 { "H", -8 },
113 { "I", -9 },
114 { "K", -10 },
115 { "L", -11 },
116 { "M", -12 },
117 { "N", 1 },
118 { "O", 2 },
119 { "P", 3 },
120 { "Q", 4 },
121 { "R", 5 },
122 { "S", 6 },
123 { "T", 7 },
124 { "U", 8 },
125 { "V", 9 },
126 { "W", 10 },
127 { "X", 11 },
128 { "Y", 12 },
129 { "Z", 0 },
130 };
131
132 bool ParseRFC822DateTime(const char* str, struct tm* time,
133 bool ret_local_time) {
134 ASSERT(str && *str);
135 ASSERT(time);
136
137 std::string str_date(str);
138 std::string str_token;
139 const char* str_curr = str_date.c_str();
140
141 str_token = SplitOneStringToken(&str_curr, kRFC822_DateDelimiters);
142 if (str_token == "") {
143 return false;
144 }
145
146 for (int i = 0; i < kNumOfDays; ++i) {
147 if (str_token == kRFC822_Day[i]) {
148 // Skip spaces after ','
149 while (*str_curr == ' ' && *str_curr != '\0') {
150 str_curr++;
151 }
152
153 str_token = SplitOneStringToken(&str_curr, kRFC822_DateDelimiters);
154 if (str_token == "") {
155 return false;
156 }
157 break;
158 }
159 }
160
161 int day = 0;
162 if (!ParseStringToInt(str_token.c_str(), &day, true) || day < 0 || day > 31) {
163 return false;
164 }
165
166 str_token = SplitOneStringToken(&str_curr, kRFC822_DateDelimiters);
167 if (str_token == "") {
168 return false;
169 }
170
171 int month = -1;
172 for (int i = 0; i < kNumOfMonth; ++i) {
173 if (str_token == kRFC822_Month[i]) {
174 month = i; // month is 0 based number
175 break;
176 }
177 }
178 if (month == -1) { // month not found
179 return false;
180 }
181
182 str_token = SplitOneStringToken(&str_curr, kRFC822_DateDelimiters);
183 if (str_token == "") {
184 return false;
185 }
186
187 int year = 0;
188 if (!ParseStringToInt(str_token.c_str(), &year, true)) {
189 return false;
190 }
191 if (year < 100) { // two digit year format, convert to 1950 - 2050 range
192 if (year < 50) {
193 year += 2000;
194 } else {
195 year += 1900;
196 }
197 }
198
199 str_token = SplitOneStringToken(&str_curr, kRFC822_TimeDelimiter);
200 if (str_token == "") {
201 return false;
202 }
203
204 int hour = 0;
205 if (!ParseStringToInt(str_token.c_str(), &hour, true) ||
206 hour < 0 || hour > 23) {
207 return false;
208 }
209
210 str_token = SplitOneStringToken(&str_curr, kRFC822_TimeDelimiter);
211 if (str_token == "") {
212 return false;
213 }
214
215 int minute = 0;
216 if (!ParseStringToInt(str_token.c_str(), &minute, true) ||
217 minute < 0 || minute > 59) {
218 return false;
219 }
220
221 str_token = SplitOneStringToken(&str_curr, kRFC822_TimeDelimiter);
222 if (str_token == "") {
223 return false;
224 }
225
226 int second = 0;
227 // distingushed between XX:XX and XX:XX:XX time formats
228 if (str_token.size() == 2 && isdigit(str_token[0]) && isdigit(str_token[1])) {
229 second = 0;
230 if (!ParseStringToInt(str_token.c_str(), &second, true) ||
231 second < 0 || second > 59) {
232 return false;
233 }
234
235 str_token = SplitOneStringToken(&str_curr, kRFC822_TimeDelimiter);
236 if (str_token == "") {
237 return false;
238 }
239 }
240
241 int bias = 0;
242 if (str_token[0] == '+' || str_token[0] == '-' || isdigit(str_token[0])) {
243 // numeric format
244 int zone = 0;
245 if (!ParseStringToInt(str_token.c_str(), &zone, true)) {
246 return false;
247 }
248
249 // zone is in HHMM format, need to convert to the number of minutes
250 bias = (zone / 100) * 60 + (zone % 100);
251 } else { // text format
252 for (size_t i = 0; i < sizeof(kRFC822_TimeZone) / sizeof(TimeZoneInfo);
253 ++i) {
254 if (str_token == kRFC822_TimeZone[i].zone_name) {
255 bias = kRFC822_TimeZone[i].hour_dif * 60;
256 break;
257 }
258 }
259 }
260
261 SetZero(*time);
262 time->tm_year = year - 1900;
263 time->tm_mon = month;
264 time->tm_mday = day;
265 time->tm_hour = hour;
266 time->tm_min = minute;
267 time->tm_sec = second;
268
269 time64 time_64 = TmToTime64(*time);
270 time_64 = time_64 - bias * kMinsTo100ns;
271
272 if (!Time64ToTm(time_64, time)) {
273 return false;
274 }
275
276 if (ret_local_time) {
277 if (!UtcTimeToLocalTime(time)) {
278 return false;
279 }
280 }
281
282 return true;
283 }
284
285 // Parse a string to time span
286 //
287 // A TimeSpan value can be represented as
288 // [d.]hh:mm:ss
289 //
290 // d = days (optional)
291 // hh = hours as measured on a 24-hour clock
292 // mm = minutes
293 // ss = seconds
294 bool ParseStringToTimeSpan(const char* str, time64* time_span) {
295 ASSERT(str);
296 ASSERT(time_span);
297
298 const char kColonDelimitor[] = ":";
299 const char kDotDelimitor = '.';
300
301 std::string str_span(str);
302 time64 span = 0;
303
304 int idx = str_span.find(kDotDelimitor);
305 if (idx != -1) {
306 std::string str_day = str_span.substr(0, idx);
307 int day = 0;
308 if (!ParseStringToInt(str_day.c_str(), &day, true) ||
309 day < 0 || day > 365) {
310 return false;
311 }
312 span = day;
313
314 str_span = str_span.substr(idx + 1);
315 }
316
317 const char* str_curr = str_span.c_str();
318 std::string str_token;
319
320 str_token = SplitOneStringToken(&str_curr, kColonDelimitor);
321 if (str_token == "") {
322 return false;
323 }
324
325 int hour = 0;
326 if (!ParseStringToInt(str_token.c_str(), &hour, true) ||
327 hour < 0 || hour > 23) {
328 return false;
329 }
330 span = span * 24 + hour;
331
332 str_token = SplitOneStringToken(&str_curr, kColonDelimitor);
333 if (str_token == "") {
334 return false;
335 }
336
337 int minute = 0;
338 if (!ParseStringToInt(str_token.c_str(), &minute, true) ||
339 minute < 0 || minute > 59) {
340 return false;
341 }
342 span = span * 60 + minute;
343
344 str_token = SplitOneStringToken(&str_curr, kColonDelimitor);
345 if (str_token == "") {
346 return false;
347 }
348
349 int second = 0;
350 if (!ParseStringToInt(str_token.c_str(), &second, true) ||
351 second < 0 || second > 59) {
352 return false;
353 }
354
355 *time_span = (span * 60 + second) * kSecsTo100ns;
356
357 return true;
358 }
359
360 } // namespace notifier
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698