1 // Copyright (c) 2012 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.
5 #include "chrome/browser/google_apis/time_util.h"
10 #include "base/string_util.h"
11 #include "base/stringprintf.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/time.h"
15 namespace google_apis
{
20 bool ParseTimezone(const base::StringPiece
& timezone
,
22 int* out_offset_to_utc_in_minutes
) {
23 DCHECK(out_offset_to_utc_in_minutes
);
25 std::vector
<base::StringPiece
> parts
;
26 int num_of_token
= Tokenize(timezone
, ":", &parts
);
29 if (!base::StringToInt(parts
[0], &hour
))
33 if (num_of_token
> 1 && !base::StringToInt(parts
[1], &minute
))
36 *out_offset_to_utc_in_minutes
= (hour
* 60 + minute
) * (ahead
? +1 : -1);
42 bool GetTimeFromString(const base::StringPiece
& raw_value
,
43 base::Time
* parsed_time
) {
44 base::StringPiece date
;
45 base::StringPiece time_and_tz
;
46 base::StringPiece time
;
47 base::Time::Exploded exploded
= {0};
48 bool has_timezone
= false;
49 int offset_to_utc_in_minutes
= 0;
51 // Splits the string into "date" part and "time" part.
53 std::vector
<base::StringPiece
> parts
;
54 if (Tokenize(raw_value
, "T", &parts
) != 2)
57 time_and_tz
= parts
[1];
60 // Parses timezone suffix on the time part if available.
62 std::vector
<base::StringPiece
> parts
;
63 if (time_and_tz
[time_and_tz
.size() - 1] == 'Z') {
64 // Timezone is 'Z' (UTC)
66 offset_to_utc_in_minutes
= 0;
68 time
.remove_suffix(1);
69 } else if (Tokenize(time_and_tz
, "+", &parts
) == 2) {
70 // Timezone is "+hh:mm" format
71 if (!ParseTimezone(parts
[1], true, &offset_to_utc_in_minutes
))
75 } else if (Tokenize(time_and_tz
, "-", &parts
) == 2) {
76 // Timezone is "-hh:mm" format
77 if (!ParseTimezone(parts
[1], false, &offset_to_utc_in_minutes
))
82 // No timezone (uses local timezone)
87 // Parses the date part.
89 std::vector
<base::StringPiece
> parts
;
90 if (Tokenize(date
, "-", &parts
) != 3)
93 if (!base::StringToInt(parts
[0], &exploded
.year
) ||
94 !base::StringToInt(parts
[1], &exploded
.month
) ||
95 !base::StringToInt(parts
[2], &exploded
.day_of_month
)) {
100 // Parses the time part.
102 std::vector
<base::StringPiece
> parts
;
103 int num_of_token
= Tokenize(time
, ":", &parts
);
104 if (num_of_token
!= 3)
107 if (!base::StringToInt(parts
[0], &exploded
.hour
) ||
108 !base::StringToInt(parts
[1], &exploded
.minute
)) {
112 std::vector
<base::StringPiece
> seconds_parts
;
113 int num_of_seconds_token
= Tokenize(parts
[2], ".", &seconds_parts
);
114 if (num_of_seconds_token
>= 3)
117 if (!base::StringToInt(seconds_parts
[0], &exploded
.second
))
120 // Only accept milli-seconds (3-digits).
121 if (num_of_seconds_token
> 1 &&
122 seconds_parts
[1].length() == 3 &&
123 !base::StringToInt(seconds_parts
[1], &exploded
.millisecond
)) {
128 exploded
.day_of_week
= 0;
129 if (!exploded
.HasValidValues())
133 *parsed_time
= base::Time::FromUTCExploded(exploded
);
134 if (offset_to_utc_in_minutes
!= 0)
135 *parsed_time
-= base::TimeDelta::FromMinutes(offset_to_utc_in_minutes
);
137 *parsed_time
= base::Time::FromLocalExploded(exploded
);
143 std::string
FormatTimeAsString(const base::Time
& time
) {
144 base::Time::Exploded exploded
;
145 time
.UTCExplode(&exploded
);
146 return base::StringPrintf(
147 "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ",
148 exploded
.year
, exploded
.month
, exploded
.day_of_month
,
149 exploded
.hour
, exploded
.minute
, exploded
.second
, exploded
.millisecond
);
152 std::string
FormatTimeAsStringLocaltime(const base::Time
& time
) {
153 base::Time::Exploded exploded
;
154 time
.LocalExplode(&exploded
);
156 return base::StringPrintf(
157 "%04d-%02d-%02dT%02d:%02d:%02d.%03d",
158 exploded
.year
, exploded
.month
, exploded
.day_of_month
,
159 exploded
.hour
, exploded
.minute
, exploded
.second
, exploded
.millisecond
);
163 } // namespace google_apis