| 128 | } |
| 129 | |
| 130 | void TimestampValue::UtcToLocal(const Timezone& local_tz, |
| 131 | TimestampValue* start_of_repeated_period, TimestampValue* end_of_repeated_period) { |
| 132 | DCHECK(HasDateAndTime()); |
| 133 | time_t unix_time; |
| 134 | if (UNLIKELY(!UtcToUnixTime(&unix_time))) { |
| 135 | SetToInvalidDateTime(); |
| 136 | return; |
| 137 | } |
| 138 | |
| 139 | cctz::time_point<cctz::sys_seconds> from_tp = UnixTimeToTimePoint(unix_time); |
| 140 | cctz::civil_second to_cs = cctz::convert(from_tp, local_tz); |
| 141 | |
| 142 | *this = CivilSecondsToTimestampValue(to_cs, time_.fractional_seconds()); |
| 143 | |
| 144 | if (start_of_repeated_period == nullptr && end_of_repeated_period == nullptr) return; |
| 145 | // Do the reverse conversion if repeated period boundaries are needed. |
| 146 | const cctz::time_zone::civil_lookup from_cl = local_tz.lookup(to_cs); |
| 147 | if (UNLIKELY(from_cl.kind == cctz::time_zone::civil_lookup::REPEATED)) { |
| 148 | if (start_of_repeated_period != nullptr) { |
| 149 | // Start of the period is simply the transition time converted to local time. |
| 150 | to_cs = cctz::convert(from_cl.trans, local_tz); |
| 151 | *start_of_repeated_period = CivilSecondsToTimestampValue(to_cs, 0); |
| 152 | } |
| 153 | if (end_of_repeated_period != nullptr) { |
| 154 | // End of the period is last nanosecond before transition time converted to |
| 155 | // local time. |
| 156 | to_cs = cctz::convert(from_cl.trans - std::chrono::seconds(1), local_tz); |
| 157 | *end_of_repeated_period = |
| 158 | CivilSecondsToTimestampValue(to_cs, NANOS_PER_SEC - 1); |
| 159 | } |
| 160 | } |
| 161 | } |
| 162 | |
| 163 | void TimestampValue::HiveLegacyUtcToLocal(const Timezone& local_tz) { |
| 164 | DCHECK(HasDateAndTime()); |