1 // Copyright 2016 Google Inc. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Parsing of a POSIX zone spec as described in the TZ part of section 8.3 in 16 // http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html. 17 // 18 // The current POSIX spec for America/Los_Angeles is "PST8PDT,M3.2.0,M11.1.0", 19 // which would be broken down as ... 20 // 21 // PosixTimeZone { 22 // std_abbr = "PST" 23 // std_offset = -28800 24 // dst_abbr = "PDT" 25 // dst_offset = -25200 26 // dst_start = PosixTransition { 27 // date { 28 // m { 29 // month = 3 30 // week = 2 31 // weekday = 0 32 // } 33 // } 34 // time { 35 // offset = 7200 36 // } 37 // } 38 // dst_end = PosixTransition { 39 // date { 40 // m { 41 // month = 11 42 // week = 1 43 // weekday = 0 44 // } 45 // } 46 // time { 47 // offset = 7200 48 // } 49 // } 50 // } 51 52 #ifndef ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_POSIX_H_ 53 #define ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_POSIX_H_ 54 55 #include <cstdint> 56 #include <string> 57 58 #include "absl/base/config.h" 59 60 namespace absl { 61 ABSL_NAMESPACE_BEGIN 62 namespace time_internal { 63 namespace cctz { 64 65 // The date/time of the transition. The date is specified as either: 66 // (J) the Nth day of the year (1 <= N <= 365), excluding leap days, or 67 // (N) the Nth day of the year (0 <= N <= 365), including leap days, or 68 // (M) the Nth weekday of a month (e.g., the 2nd Sunday in March). 69 // The time, specified as a day offset, identifies the particular moment 70 // of the transition, and may be negative or >= 24h, and in which case 71 // it would take us to another day, and perhaps week, or even month. 72 struct PosixTransition { 73 enum DateFormat { J, N, M }; 74 75 struct Date { 76 struct NonLeapDay { 77 std::int_fast16_t day; // day of non-leap year [1:365] 78 }; 79 struct Day { 80 std::int_fast16_t day; // day of year [0:365] 81 }; 82 struct MonthWeekWeekday { 83 std::int_fast8_t month; // month of year [1:12] 84 std::int_fast8_t week; // week of month [1:5] (5==last) 85 std::int_fast8_t weekday; // 0==Sun, ..., 6=Sat 86 }; 87 88 DateFormat fmt; 89 90 union { 91 NonLeapDay j; 92 Day n; 93 MonthWeekWeekday m; 94 }; 95 }; 96 97 struct Time { 98 std::int_fast32_t offset; // seconds before/after 00:00:00 99 }; 100 101 Date date; 102 Time time; 103 }; 104 105 // The entirety of a POSIX-string specified time-zone rule. The standard 106 // abbreviation and offset are always given. If the time zone includes 107 // daylight saving, then the daylight abbrevation is non-empty and the 108 // remaining fields are also valid. Note that the start/end transitions 109 // are not ordered---in the southern hemisphere the transition to end 110 // daylight time occurs first in any particular year. 111 struct PosixTimeZone { 112 std::string std_abbr; 113 std::int_fast32_t std_offset; 114 115 std::string dst_abbr; 116 std::int_fast32_t dst_offset; 117 PosixTransition dst_start; 118 PosixTransition dst_end; 119 }; 120 121 // Breaks down a POSIX time-zone specification into its constituent pieces, 122 // filling in any missing values (DST offset, or start/end transition times) 123 // with the standard-defined defaults. Returns false if the specification 124 // could not be parsed (although some fields of *res may have been altered). 125 bool ParsePosixSpec(const std::string& spec, PosixTimeZone* res); 126 127 } // namespace cctz 128 } // namespace time_internal 129 ABSL_NAMESPACE_END 130 } // namespace absl 131 132 #endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_POSIX_H_ 133