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 "google_apis/drive/time_util.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/time/time.h"
15 namespace google_apis
{
20 const char kNullTimeString
[] = "null";
22 bool ParseTimezone(const base::StringPiece
& timezone
,
24 int* out_offset_to_utc_in_minutes
) {
25 DCHECK(out_offset_to_utc_in_minutes
);
27 std::vector
<base::StringPiece
> parts
;
28 int num_of_token
= Tokenize(timezone
, ":", &parts
);
31 if (!base::StringToInt(parts
[0], &hour
))
35 if (num_of_token
> 1 && !base::StringToInt(parts
[1], &minute
))
38 *out_offset_to_utc_in_minutes
= (hour
* 60 + minute
) * (ahead
? +1 : -1);
44 bool GetTimeFromString(const base::StringPiece
& raw_value
,
45 base::Time
* parsed_time
) {
46 base::StringPiece date
;
47 base::StringPiece time_and_tz
;
48 base::StringPiece time
;
49 base::Time::Exploded exploded
= {0};
50 bool has_timezone
= false;
51 int offset_to_utc_in_minutes
= 0;
53 // Splits the string into "date" part and "time" part.
55 std::vector
<base::StringPiece
> parts
;
56 if (Tokenize(raw_value
, "T", &parts
) != 2)
59 time_and_tz
= parts
[1];
62 // Parses timezone suffix on the time part if available.
64 std::vector
<base::StringPiece
> parts
;
65 if (time_and_tz
[time_and_tz
.size() - 1] == 'Z') {
66 // Timezone is 'Z' (UTC)
68 offset_to_utc_in_minutes
= 0;
70 time
.remove_suffix(1);
71 } else if (Tokenize(time_and_tz
, "+", &parts
) == 2) {
72 // Timezone is "+hh:mm" format
73 if (!ParseTimezone(parts
[1], true, &offset_to_utc_in_minutes
))
77 } else if (Tokenize(time_and_tz
, "-", &parts
) == 2) {
78 // Timezone is "-hh:mm" format
79 if (!ParseTimezone(parts
[1], false, &offset_to_utc_in_minutes
))
84 // No timezone (uses local timezone)
89 // Parses the date part.
91 std::vector
<base::StringPiece
> parts
;
92 if (Tokenize(date
, "-", &parts
) != 3)
95 if (!base::StringToInt(parts
[0], &exploded
.year
) ||
96 !base::StringToInt(parts
[1], &exploded
.month
) ||
97 !base::StringToInt(parts
[2], &exploded
.day_of_month
)) {
102 // Parses the time part.
104 std::vector
<base::StringPiece
> parts
;
105 int num_of_token
= Tokenize(time
, ":", &parts
);
106 if (num_of_token
!= 3)
109 if (!base::StringToInt(parts
[0], &exploded
.hour
) ||
110 !base::StringToInt(parts
[1], &exploded
.minute
)) {
114 std::vector
<base::StringPiece
> seconds_parts
;
115 int num_of_seconds_token
= Tokenize(parts
[2], ".", &seconds_parts
);
116 if (num_of_seconds_token
>= 3)
119 if (!base::StringToInt(seconds_parts
[0], &exploded
.second
))
122 // Only accept milli-seconds (3-digits).
123 if (num_of_seconds_token
> 1 &&
124 seconds_parts
[1].length() == 3 &&
125 !base::StringToInt(seconds_parts
[1], &exploded
.millisecond
)) {
130 exploded
.day_of_week
= 0;
131 if (!exploded
.HasValidValues())
135 *parsed_time
= base::Time::FromUTCExploded(exploded
);
136 if (offset_to_utc_in_minutes
!= 0)
137 *parsed_time
-= base::TimeDelta::FromMinutes(offset_to_utc_in_minutes
);
139 *parsed_time
= base::Time::FromLocalExploded(exploded
);
145 std::string
FormatTimeAsString(const base::Time
& time
) {
147 return kNullTimeString
;
149 base::Time::Exploded exploded
;
150 time
.UTCExplode(&exploded
);
151 return base::StringPrintf(
152 "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ",
153 exploded
.year
, exploded
.month
, exploded
.day_of_month
,
154 exploded
.hour
, exploded
.minute
, exploded
.second
, exploded
.millisecond
);
157 std::string
FormatTimeAsStringLocaltime(const base::Time
& time
) {
159 return kNullTimeString
;
161 base::Time::Exploded exploded
;
162 time
.LocalExplode(&exploded
);
163 return base::StringPrintf(
164 "%04d-%02d-%02dT%02d:%02d:%02d.%03d",
165 exploded
.year
, exploded
.month
, exploded
.day_of_month
,
166 exploded
.hour
, exploded
.minute
, exploded
.second
, exploded
.millisecond
);
170 } // namespace google_apis