Index: chrome/browser/sync/notifier/base/time.cc |
=================================================================== |
--- chrome/browser/sync/notifier/base/time.cc (revision 0) |
+++ chrome/browser/sync/notifier/base/time.cc (revision 0) |
@@ -0,0 +1,360 @@ |
+// Copyright (c) 2009 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "chrome/browser/sync/notifier/base/time.h" |
+ |
+#include <string> |
+#include <time.h> |
+ |
+#include "chrome/browser/sync/notifier/base/string.h" |
+#include "chrome/browser/sync/notifier/base/utils.h" |
+#include "talk/base/common.h" |
+#include "talk/base/logging.h" |
+ |
+namespace notifier { |
+ |
+// Get the current time represented in 100NS granularity since epoch |
+// (Jan 1, 1970) |
+time64 GetCurrent100NSTimeSinceEpoch() { |
+ return GetCurrent100NSTime() - kStart100NsTimeToEpoch; |
+} |
+ |
+char* GetLocalTimeAsString() { |
+ time64 long_time = GetCurrent100NSTime(); |
+ struct tm now; |
+ Time64ToTm(long_time, &now); |
+ char* time_string = asctime(&now); |
+ if (time_string) { |
+ int time_len = strlen(time_string); |
+ if (time_len > 0) { |
+ time_string[time_len - 1] = 0; // trim off terminating \n |
+ } |
+ } |
+ return time_string; |
+} |
+ |
+// Parses RFC 822 Date/Time format |
+// 5. DATE AND TIME SPECIFICATION |
+// 5.1. SYNTAX |
+// |
+// date-time = [ day "," ] date time ; dd mm yy |
+// ; hh:mm:ss zzz |
+// day = "Mon" / "Tue" / "Wed" / "Thu" |
+// / "Fri" / "Sat" / "Sun" |
+// |
+// date = 1*2DIGIT month 2DIGIT ; day month year |
+// ; e.g. 20 Jun 82 |
+// |
+// month = "Jan" / "Feb" / "Mar" / "Apr" |
+// / "May" / "Jun" / "Jul" / "Aug" |
+// / "Sep" / "Oct" / "Nov" / "Dec" |
+// |
+// time = hour zone ; ANSI and Military |
+// |
+// hour = 2DIGIT ":" 2DIGIT [":" 2DIGIT] |
+// ; 00:00:00 - 23:59:59 |
+// |
+// zone = "UT" / "GMT" ; Universal Time |
+// ; North American : UT |
+// / "EST" / "EDT" ; Eastern: - 5/ - 4 |
+// / "CST" / "CDT" ; Central: - 6/ - 5 |
+// / "MST" / "MDT" ; Mountain: - 7/ - 6 |
+// / "PST" / "PDT" ; Pacific: - 8/ - 7 |
+// / 1ALPHA ; Military: Z = UT; |
+// ; A:-1; (J not used) |
+// ; M:-12; N:+1; Y:+12 |
+// / ( ("+" / "-") 4DIGIT ) ; Local differential |
+// ; hours+min. (HHMM) |
+// Return local time if ret_local_time == true, return UTC time otherwise |
+const int kNumOfDays = 7; |
+const int kNumOfMonth = 12; |
+// Note: RFC822 does not include '-' as a separator, but Http Cookies use |
+// it in the date field, like this: Wdy, DD-Mon-YYYY HH:MM:SS GMT |
+// This differs from RFC822 only by those dashes. It is legacy quirk from |
+// old Netscape cookie specification. So it makes sense to expand this |
+// parser rather then add another one. |
+// See http://wp.netscape.com/newsref/std/cookie_spec.html |
+const char kRFC822_DateDelimiters[] = " ,:-"; |
+ |
+const char kRFC822_TimeDelimiter[] = ": "; |
+const char* kRFC822_Day[] = { |
+ "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" |
+}; |
+const char* kRFC822_Month[] = { |
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun", |
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" |
+}; |
+ |
+struct TimeZoneInfo { |
+ const char* zone_name; |
+ int hour_dif; |
+}; |
+ |
+const TimeZoneInfo kRFC822_TimeZone[] = { |
+ { "UT", 0 }, |
+ { "GMT", 0 }, |
+ { "EST", -5 }, |
+ { "EDT", -4 }, |
+ { "CST", -6 }, |
+ { "CDT", -5 }, |
+ { "MST", -7 }, |
+ { "MDT", -6 }, |
+ { "PST", -8 }, |
+ { "PDT", -7 }, |
+ { "A", -1 }, // Military time zones |
+ { "B", -2 }, |
+ { "C", -3 }, |
+ { "D", -4 }, |
+ { "E", -5 }, |
+ { "F", -6 }, |
+ { "G", -7 }, |
+ { "H", -8 }, |
+ { "I", -9 }, |
+ { "K", -10 }, |
+ { "L", -11 }, |
+ { "M", -12 }, |
+ { "N", 1 }, |
+ { "O", 2 }, |
+ { "P", 3 }, |
+ { "Q", 4 }, |
+ { "R", 5 }, |
+ { "S", 6 }, |
+ { "T", 7 }, |
+ { "U", 8 }, |
+ { "V", 9 }, |
+ { "W", 10 }, |
+ { "X", 11 }, |
+ { "Y", 12 }, |
+ { "Z", 0 }, |
+}; |
+ |
+bool ParseRFC822DateTime(const char* str, struct tm* time, |
+ bool ret_local_time) { |
+ ASSERT(str && *str); |
+ ASSERT(time); |
+ |
+ std::string str_date(str); |
+ std::string str_token; |
+ const char* str_curr = str_date.c_str(); |
+ |
+ str_token = SplitOneStringToken(&str_curr, kRFC822_DateDelimiters); |
+ if (str_token == "") { |
+ return false; |
+ } |
+ |
+ for (int i = 0; i < kNumOfDays; ++i) { |
+ if (str_token == kRFC822_Day[i]) { |
+ // Skip spaces after ',' |
+ while (*str_curr == ' ' && *str_curr != '\0') { |
+ str_curr++; |
+ } |
+ |
+ str_token = SplitOneStringToken(&str_curr, kRFC822_DateDelimiters); |
+ if (str_token == "") { |
+ return false; |
+ } |
+ break; |
+ } |
+ } |
+ |
+ int day = 0; |
+ if (!ParseStringToInt(str_token.c_str(), &day, true) || day < 0 || day > 31) { |
+ return false; |
+ } |
+ |
+ str_token = SplitOneStringToken(&str_curr, kRFC822_DateDelimiters); |
+ if (str_token == "") { |
+ return false; |
+ } |
+ |
+ int month = -1; |
+ for (int i = 0; i < kNumOfMonth; ++i) { |
+ if (str_token == kRFC822_Month[i]) { |
+ month = i; // month is 0 based number |
+ break; |
+ } |
+ } |
+ if (month == -1) { // month not found |
+ return false; |
+ } |
+ |
+ str_token = SplitOneStringToken(&str_curr, kRFC822_DateDelimiters); |
+ if (str_token == "") { |
+ return false; |
+ } |
+ |
+ int year = 0; |
+ if (!ParseStringToInt(str_token.c_str(), &year, true)) { |
+ return false; |
+ } |
+ if (year < 100) { // two digit year format, convert to 1950 - 2050 range |
+ if (year < 50) { |
+ year += 2000; |
+ } else { |
+ year += 1900; |
+ } |
+ } |
+ |
+ str_token = SplitOneStringToken(&str_curr, kRFC822_TimeDelimiter); |
+ if (str_token == "") { |
+ return false; |
+ } |
+ |
+ int hour = 0; |
+ if (!ParseStringToInt(str_token.c_str(), &hour, true) || |
+ hour < 0 || hour > 23) { |
+ return false; |
+ } |
+ |
+ str_token = SplitOneStringToken(&str_curr, kRFC822_TimeDelimiter); |
+ if (str_token == "") { |
+ return false; |
+ } |
+ |
+ int minute = 0; |
+ if (!ParseStringToInt(str_token.c_str(), &minute, true) || |
+ minute < 0 || minute > 59) { |
+ return false; |
+ } |
+ |
+ str_token = SplitOneStringToken(&str_curr, kRFC822_TimeDelimiter); |
+ if (str_token == "") { |
+ return false; |
+ } |
+ |
+ int second = 0; |
+ // distingushed between XX:XX and XX:XX:XX time formats |
+ if (str_token.size() == 2 && isdigit(str_token[0]) && isdigit(str_token[1])) { |
+ second = 0; |
+ if (!ParseStringToInt(str_token.c_str(), &second, true) || |
+ second < 0 || second > 59) { |
+ return false; |
+ } |
+ |
+ str_token = SplitOneStringToken(&str_curr, kRFC822_TimeDelimiter); |
+ if (str_token == "") { |
+ return false; |
+ } |
+ } |
+ |
+ int bias = 0; |
+ if (str_token[0] == '+' || str_token[0] == '-' || isdigit(str_token[0])) { |
+ // numeric format |
+ int zone = 0; |
+ if (!ParseStringToInt(str_token.c_str(), &zone, true)) { |
+ return false; |
+ } |
+ |
+ // zone is in HHMM format, need to convert to the number of minutes |
+ bias = (zone / 100) * 60 + (zone % 100); |
+ } else { // text format |
+ for (size_t i = 0; i < sizeof(kRFC822_TimeZone) / sizeof(TimeZoneInfo); |
+ ++i) { |
+ if (str_token == kRFC822_TimeZone[i].zone_name) { |
+ bias = kRFC822_TimeZone[i].hour_dif * 60; |
+ break; |
+ } |
+ } |
+ } |
+ |
+ SetZero(*time); |
+ time->tm_year = year - 1900; |
+ time->tm_mon = month; |
+ time->tm_mday = day; |
+ time->tm_hour = hour; |
+ time->tm_min = minute; |
+ time->tm_sec = second; |
+ |
+ time64 time_64 = TmToTime64(*time); |
+ time_64 = time_64 - bias * kMinsTo100ns; |
+ |
+ if (!Time64ToTm(time_64, time)) { |
+ return false; |
+ } |
+ |
+ if (ret_local_time) { |
+ if (!UtcTimeToLocalTime(time)) { |
+ return false; |
+ } |
+ } |
+ |
+ return true; |
+} |
+ |
+// Parse a string to time span |
+// |
+// A TimeSpan value can be represented as |
+// [d.]hh:mm:ss |
+// |
+// d = days (optional) |
+// hh = hours as measured on a 24-hour clock |
+// mm = minutes |
+// ss = seconds |
+bool ParseStringToTimeSpan(const char* str, time64* time_span) { |
+ ASSERT(str); |
+ ASSERT(time_span); |
+ |
+ const char kColonDelimitor[] = ":"; |
+ const char kDotDelimitor = '.'; |
+ |
+ std::string str_span(str); |
+ time64 span = 0; |
+ |
+ int idx = str_span.find(kDotDelimitor); |
+ if (idx != -1) { |
+ std::string str_day = str_span.substr(0, idx); |
+ int day = 0; |
+ if (!ParseStringToInt(str_day.c_str(), &day, true) || |
+ day < 0 || day > 365) { |
+ return false; |
+ } |
+ span = day; |
+ |
+ str_span = str_span.substr(idx + 1); |
+ } |
+ |
+ const char* str_curr = str_span.c_str(); |
+ std::string str_token; |
+ |
+ str_token = SplitOneStringToken(&str_curr, kColonDelimitor); |
+ if (str_token == "") { |
+ return false; |
+ } |
+ |
+ int hour = 0; |
+ if (!ParseStringToInt(str_token.c_str(), &hour, true) || |
+ hour < 0 || hour > 23) { |
+ return false; |
+ } |
+ span = span * 24 + hour; |
+ |
+ str_token = SplitOneStringToken(&str_curr, kColonDelimitor); |
+ if (str_token == "") { |
+ return false; |
+ } |
+ |
+ int minute = 0; |
+ if (!ParseStringToInt(str_token.c_str(), &minute, true) || |
+ minute < 0 || minute > 59) { |
+ return false; |
+ } |
+ span = span * 60 + minute; |
+ |
+ str_token = SplitOneStringToken(&str_curr, kColonDelimitor); |
+ if (str_token == "") { |
+ return false; |
+ } |
+ |
+ int second = 0; |
+ if (!ParseStringToInt(str_token.c_str(), &second, true) || |
+ second < 0 || second > 59) { |
+ return false; |
+ } |
+ |
+ *time_span = (span * 60 + second) * kSecsTo100ns; |
+ |
+ return true; |
+} |
+ |
+} // namespace notifier |
Property changes on: chrome\browser\sync\notifier\base\time.cc |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |