/* * This file is a part of Winix * and is distributed under the 2-Clause BSD licence. * Author: Tomasz Sowa */ /* * Copyright (c) 2012-2023, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #ifndef headerfile_winix_core_timezone #define headerfile_winix_core_timezone #include #include #include "date/date.h" #include "space/space.h" namespace Winix { class TimeZone { public: struct DstDate { enum DateType { ordinary_date = 0, first_weekday, last_weekday, }; /* * for ordinary_date * */ DateType date_type; /* * a week day (0-sunday, 1-monday, ..., 6-saturday) * used when date_type is first_weekday or last_weekday */ int weekday; /* * if date_type=ordinary_date the date is used as normal date represented in UTC time * if date_type=first_weekday we are looking for a first weekday in the date.month (year will be changed) * if date_type=last_weekday we are looking for the last weekady in the date.month (year will be changed) */ pt::Date date; DstDate(); void Clear(); int Compare(const pt::Date & utc_date) const; static pt::Date CalculateRelativeDate(int year, int month, bool is_first, int weekday, int hour, int min, int sec); }; struct Dst { /* * true if a time zone has daylight saving time */ bool has_dst; /* * time zone daylight saving time (used if has_dst is true) */ DstDate start, end; /* * time zone daylight saving time offset * used when has_dst is true and the date is whithin start and end * this offset should be added to time zone offset */ time_t offset; Dst(); void Clear(); /* * checking whether specified 'date' is in the range of Dst * has_dst must be true */ bool IsDstUsed(const pt::Date & utc_date) const; }; TimeZone(); void Clear(); /* reading zime zone values from Space struct (tz_id is skipped) the space struct should have: "tz_offset" (long) "tz_has_dst" (bool) if tz_has_dst is true then also: "tz_dst_start" date in the following format: MM:DD HH[:MM[:SS]] "tz_dst_end" the same as above "tz_dst_offset" (long) */ bool SetTz(pt::Space & space); /* converting from UTC to local time */ time_t CalcLocalOffset(const pt::Date & utc_date); time_t ToLocal(time_t utc_time); pt::Date ToLocal(const pt::Date & utc_date); static void PrintOffset(time_t offset, pt::Stream & str); // prints the offset as [+|-]HH:MM:SS e.g.: +02:00:00 /* converting from local time to UTC */ time_t CalcUTCOffset(const pt::Date & local_date); time_t ToUTC(time_t local_time); pt::Date ToUTC(const pt::Date & local_date); // return a Dst structure for the specified year // or null if it not exists // this method can return a Dst structure for earlier year than 'year' // if 'year' doesn't exist Dst * FindDst(int year); // a time zone name // this is a key to locale std::wstring name; // each locale has its own identifier size_t id; // time zone offset (in seconds) time_t offset; // daylight saving time map // year -> Dst // if there is not a specified year we are taking the lower year, e.g. // if we are looking for 2010 and there is no such a year then we take 2009 // (or 2008 if 2009 not exists etc) typedef std::map DstMap; DstMap dst_map; private: time_t ParseStrOffset(const wchar_t * str); time_t GetOffset(pt::Space & space); int ParseDstDateWeekday(const wchar_t * date_str, const wchar_t ** after_date_str); const wchar_t * SkipDstDateSeparator(const wchar_t * date_str); bool ParseDstDate(int year, const wchar_t * date_str, DstDate & dst_date); bool SetTzDst(pt::Space & year); static void PrintOffsetPart(long val, pt::Stream & str); }; } // namespace Winix #endif