| 187 | } |
| 188 | |
| 189 | void TimestampValue::LocalToUtc(const Timezone& local_tz, |
| 190 | TimestampValue* pre_utc_if_repeated, TimestampValue* post_utc_if_repeated) { |
| 191 | DCHECK(HasDateAndTime()); |
| 192 | // Time-zone conversion rules don't affect fractional seconds, leave them intact. |
| 193 | const auto nanos = nanoseconds(time_.fractional_seconds()); |
| 194 | const cctz::civil_second from_cs(date_.year(), date_.month(), date_.day(), |
| 195 | time_.hours(), time_.minutes(), time_.seconds()); |
| 196 | |
| 197 | // 'from_cl' represents the 'time_point' that corresponds to 'from_cs' civil time within |
| 198 | // 'local_tz' time-zone. |
| 199 | const cctz::time_zone::civil_lookup from_cl = local_tz.lookup(from_cs); |
| 200 | |
| 201 | if (LIKELY(from_cl.kind == cctz::time_zone::civil_lookup::UNIQUE)) { |
| 202 | *this = UtcFromUnixTimeTicks<1>(TimePointToUnixTime(from_cl.pre)); |
| 203 | time_ += nanos; |
| 204 | return; |
| 205 | } |
| 206 | |
| 207 | // In case the resulting 'time_point' is ambiguous, we have to invalidate this |
| 208 | // TimestampValue and set pre/post_utc_if_repeated if needed. |
| 209 | // 'civil_lookup' members and the details of handling ambiguity are described at: |
| 210 | // https://github.com/google/cctz/blob/a2dd3d0fbc811fe0a1d4d2dbb0341f1a3d28cb2a/ |
| 211 | // include/cctz/time_zone.h#L106 |
| 212 | SetToInvalidDateTime(); |
| 213 | if (from_cl.kind == cctz::time_zone::civil_lookup::REPEATED){ |
| 214 | if (pre_utc_if_repeated != nullptr) { |
| 215 | *pre_utc_if_repeated = UtcFromUnixTimeTicks<1>(TimePointToUnixTime(from_cl.pre)); |
| 216 | pre_utc_if_repeated->time_ += nanos; |
| 217 | } |
| 218 | if (post_utc_if_repeated != nullptr) { |
| 219 | *post_utc_if_repeated = UtcFromUnixTimeTicks<1>(TimePointToUnixTime(from_cl.post)); |
| 220 | post_utc_if_repeated->time_ += nanos; |
| 221 | } |
| 222 | } else { |
| 223 | DCHECK(from_cl.kind == cctz::time_zone::civil_lookup::SKIPPED); |
| 224 | if (pre_utc_if_repeated != nullptr) { |
| 225 | *pre_utc_if_repeated = UtcFromUnixTimeTicks<1>(TimePointToUnixTime(from_cl.trans)); |
| 226 | pre_utc_if_repeated->time_ += nanos; |
| 227 | } |
| 228 | if (post_utc_if_repeated != nullptr) { |
| 229 | *post_utc_if_repeated = UtcFromUnixTimeTicks<1>(TimePointToUnixTime(from_cl.trans)); |
| 230 | post_utc_if_repeated->time_ += nanos; |
| 231 | } |
| 232 | } |
| 233 | } |
| 234 | |
| 235 | ostream& operator<<(ostream& os, const TimestampValue& timestamp_value) { |
| 236 | char dst[SimpleDateFormatTokenizer::DEFAULT_DATE_TIME_FMT_LEN + 1]; |