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 // http://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 CCTZ_TIME_ZONE_POSIX_H_ 53 #define CCTZ_TIME_ZONE_POSIX_H_ 54 55 #include <cstdint> 56 #include <string> 57 58 namespace cctz { 59 60 // The date/time of the transition. The date is specified as either: 61 // (J) the Nth day of the year (1 <= N <= 365), excluding leap days, or 62 // (N) the Nth day of the year (0 <= N <= 365), including leap days, or 63 // (M) the Nth weekday of a month (e.g., the 2nd Sunday in March). 64 // The time, specified as a day offset, identifies the particular moment 65 // of the transition, and may be negative or >= 24h, and in which case 66 // it would take us to another day, and perhaps week, or even month. 67 struct PosixTransition { 68 enum DateFormat { J, N, M }; 69 struct { 70 DateFormat fmt; 71 union { 72 struct { 73 std::int_fast16_t day; // day of non-leap year [1:365] 74 } j; 75 struct { 76 std::int_fast16_t day; // day of year [0:365] 77 } n; 78 struct { 79 std::int_fast8_t month; // month of year [1:12] 80 std::int_fast8_t week; // week of month [1:5] (5==last) 81 std::int_fast8_t weekday; // 0==Sun, ..., 6=Sat 82 } m; 83 }; 84 } date; 85 struct { 86 std::int_fast32_t offset; // seconds before/after 00:00:00 87 } time; 88 }; 89 90 // The entirety of a POSIX-string specified time-zone rule. The standard 91 // abbreviation and offset are always given. If the time zone includes 92 // daylight saving, then the daylight abbrevation is non-empty and the 93 // remaining fields are also valid. Note that the start/end transitions 94 // are not ordered---in the southern hemisphere the transition to end 95 // daylight time occurs first in any particular year. 96 struct PosixTimeZone { 97 std::string std_abbr; 98 std::int_fast32_t std_offset; 99 100 std::string dst_abbr; 101 std::int_fast32_t dst_offset; 102 PosixTransition dst_start; 103 PosixTransition dst_end; 104 }; 105 106 // Breaks down a POSIX time-zone specification into its constituent pieces, 107 // filling in any missing values (DST offset, or start/end transition times) 108 // with the standard-defined defaults. Returns false if the specification 109 // could not be parsed (although some fields of *res may have been altered). 110 bool ParsePosixSpec(const std::string& spec, PosixTimeZone* res); 111 112 } // namespace cctz 113 114 #endif // CCTZ_TIME_ZONE_POSIX_H_ 115