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_split.h"
12 #include "base/strings/string_util.h"
13 #include "base/strings/stringprintf.h"
14 #include "base/time/time.h"
16 namespace google_apis
{
21 const char kNullTimeString
[] = "null";
23 bool ParseTimezone(const base::StringPiece
& timezone
,
25 int* out_offset_to_utc_in_minutes
) {
26 DCHECK(out_offset_to_utc_in_minutes
);
28 std::vector
<base::StringPiece
> parts
= base::SplitStringPiece(
29 timezone
, ":", base::KEEP_WHITESPACE
, base::SPLIT_WANT_NONEMPTY
);
32 if (parts
.empty() || !base::StringToInt(parts
[0], &hour
))
36 if (parts
.size() > 1 && !base::StringToInt(parts
[1], &minute
))
39 *out_offset_to_utc_in_minutes
= (hour
* 60 + minute
) * (ahead
? +1 : -1);
45 bool GetTimeFromString(const base::StringPiece
& raw_value
,
46 base::Time
* parsed_time
) {
47 base::StringPiece date
;
48 base::StringPiece time_and_tz
;
49 base::StringPiece time
;
50 base::Time::Exploded exploded
= {0};
51 bool has_timezone
= false;
52 int offset_to_utc_in_minutes
= 0;
54 // Splits the string into "date" part and "time" part.
56 std::vector
<base::StringPiece
> parts
= base::SplitStringPiece(
57 raw_value
, "T", base::KEEP_WHITESPACE
, base::SPLIT_WANT_NONEMPTY
);
58 if (parts
.size() != 2)
61 time_and_tz
= parts
[1];
64 // Parses timezone suffix on the time part if available.
66 std::vector
<base::StringPiece
> parts
;
67 if (time_and_tz
[time_and_tz
.size() - 1] == 'Z') {
68 // Timezone is 'Z' (UTC)
70 offset_to_utc_in_minutes
= 0;
72 time
.remove_suffix(1);
74 parts
= base::SplitStringPiece(
75 time_and_tz
, "+", base::KEEP_WHITESPACE
, base::SPLIT_WANT_NONEMPTY
);
76 if (parts
.size() == 2) {
77 // Timezone is "+hh:mm" format
78 if (!ParseTimezone(parts
[1], true, &offset_to_utc_in_minutes
))
83 parts
= base::SplitStringPiece(
84 time_and_tz
, "-", base::KEEP_WHITESPACE
, base::SPLIT_WANT_NONEMPTY
);
85 if (parts
.size() == 2) {
86 // Timezone is "-hh:mm" format
87 if (!ParseTimezone(parts
[1], false, &offset_to_utc_in_minutes
))
92 // No timezone (uses local timezone)
99 // Parses the date part.
101 std::vector
<base::StringPiece
> parts
= base::SplitStringPiece(
102 date
, "-", base::KEEP_WHITESPACE
, base::SPLIT_WANT_NONEMPTY
);
103 if (parts
.size() != 3)
106 if (!base::StringToInt(parts
[0], &exploded
.year
) ||
107 !base::StringToInt(parts
[1], &exploded
.month
) ||
108 !base::StringToInt(parts
[2], &exploded
.day_of_month
)) {
113 // Parses the time part.
115 std::vector
<base::StringPiece
> parts
= base::SplitStringPiece(
116 time
, ":", base::KEEP_WHITESPACE
, base::SPLIT_WANT_NONEMPTY
);
117 if (parts
.size() != 3)
120 if (!base::StringToInt(parts
[0], &exploded
.hour
) ||
121 !base::StringToInt(parts
[1], &exploded
.minute
)) {
125 std::vector
<base::StringPiece
> seconds_parts
= base::SplitStringPiece(
126 parts
[2], ".", base::KEEP_WHITESPACE
, base::SPLIT_WANT_NONEMPTY
);
127 if (seconds_parts
.size() >= 3)
130 if (!base::StringToInt(seconds_parts
[0], &exploded
.second
))
133 // Only accept milli-seconds (3-digits).
134 if (seconds_parts
.size() > 1 &&
135 seconds_parts
[1].length() == 3 &&
136 !base::StringToInt(seconds_parts
[1], &exploded
.millisecond
)) {
141 exploded
.day_of_week
= 0;
142 if (!exploded
.HasValidValues())
146 *parsed_time
= base::Time::FromUTCExploded(exploded
);
147 if (offset_to_utc_in_minutes
!= 0)
148 *parsed_time
-= base::TimeDelta::FromMinutes(offset_to_utc_in_minutes
);
150 *parsed_time
= base::Time::FromLocalExploded(exploded
);
156 std::string
FormatTimeAsString(const base::Time
& time
) {
158 return kNullTimeString
;
160 base::Time::Exploded exploded
;
161 time
.UTCExplode(&exploded
);
162 return base::StringPrintf(
163 "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ",
164 exploded
.year
, exploded
.month
, exploded
.day_of_month
,
165 exploded
.hour
, exploded
.minute
, exploded
.second
, exploded
.millisecond
);
168 std::string
FormatTimeAsStringLocaltime(const base::Time
& time
) {
170 return kNullTimeString
;
172 base::Time::Exploded exploded
;
173 time
.LocalExplode(&exploded
);
174 return base::StringPrintf(
175 "%04d-%02d-%02dT%02d:%02d:%02d.%03d",
176 exploded
.year
, exploded
.month
, exploded
.day_of_month
,
177 exploded
.hour
, exploded
.minute
, exploded
.second
, exploded
.millisecond
);
181 } // namespace google_apis