commit
						9baf00bbfe
					
				@ -64,10 +64,19 @@ set(INCLUDE_FILES
 | 
			
		||||
  drivers/Cst816s.h
 | 
			
		||||
  FreeRTOS/portmacro.h
 | 
			
		||||
  FreeRTOS/portmacro_cmsis.h
 | 
			
		||||
  libs/date/includes/date/tz.h
 | 
			
		||||
  libs/date/includes/date/chrono_io.h
 | 
			
		||||
  libs/date/includes/date/date.h
 | 
			
		||||
  libs/date/includes/date/islamic.h
 | 
			
		||||
  libs/date/includes/date/iso_week.h
 | 
			
		||||
  libs/date/includes/date/julian.h
 | 
			
		||||
  libs/date/includes/date/ptz.h
 | 
			
		||||
  libs/date/includes/date/tz_private.h
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
include_directories(
 | 
			
		||||
  FreeRTOS/
 | 
			
		||||
  libs/date/includes
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
nRF5x_addExecutable(pinetime-app "${SOURCE_FILES}")
 | 
			
		||||
@ -9,6 +9,9 @@
 | 
			
		||||
#include <queue.h>
 | 
			
		||||
#include <Components/DateTime/DateTimeController.h>
 | 
			
		||||
#include <drivers/Cst816s.h>
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <date/date.h>
 | 
			
		||||
 | 
			
		||||
using namespace Pinetime::Applications;
 | 
			
		||||
 | 
			
		||||
@ -102,6 +105,11 @@ void DisplayApp::InitHw() {
 | 
			
		||||
  gfx->DrawString(10, 0, 0x0000, "BLE", &smallFont, false);
 | 
			
		||||
  gfx->DrawString(20, 180, 0xffff, "", &smallFont, false);
 | 
			
		||||
 | 
			
		||||
  currentChar[0] = 0;
 | 
			
		||||
  currentChar[1] = 0;
 | 
			
		||||
  currentChar[2] = 0;
 | 
			
		||||
  currentChar[3] = 0;
 | 
			
		||||
 | 
			
		||||
  touchPanel.Init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -138,11 +146,6 @@ void DisplayApp::Refresh() {
 | 
			
		||||
        state = States::Running;
 | 
			
		||||
        break;
 | 
			
		||||
      case Messages::UpdateDateTime:
 | 
			
		||||
        deltaSeconds = nrf_rtc_counter_get(portNRF_RTC_REG) / 1000;
 | 
			
		||||
        this->seconds = dateTimeController.Seconds();
 | 
			
		||||
        this->minutes = dateTimeController.Minutes();
 | 
			
		||||
        this->hours = dateTimeController.Hours();
 | 
			
		||||
        dateUpdated = true;
 | 
			
		||||
        break;
 | 
			
		||||
      case Messages::UpdateBleConnection:
 | 
			
		||||
        bleConnectionUpdated = true;
 | 
			
		||||
@ -181,18 +184,35 @@ void DisplayApp::RunningState() {
 | 
			
		||||
  auto raw = systick_counter / 1000;
 | 
			
		||||
  auto currentDeltaSeconds = raw - deltaSeconds;
 | 
			
		||||
 | 
			
		||||
  auto deltaMinutes = (currentDeltaSeconds / 60);
 | 
			
		||||
  auto currentMinutes = minutes + deltaMinutes;
 | 
			
		||||
  std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds> currentDateTime;
 | 
			
		||||
  currentDateTime += date::years( dateTimeController.Year()-1970);
 | 
			
		||||
  currentDateTime += date::days( dateTimeController.Day() - 1);
 | 
			
		||||
  currentDateTime += date::months( (int)dateTimeController.Month() - 1);
 | 
			
		||||
 | 
			
		||||
  auto deltaHours = currentMinutes / 60;
 | 
			
		||||
  currentMinutes -= (deltaHours * 60);
 | 
			
		||||
  auto currentHours = hours + deltaHours;
 | 
			
		||||
  currentDateTime += std::chrono::hours(dateTimeController.Hours());
 | 
			
		||||
  currentDateTime += std::chrono::minutes (dateTimeController.Minutes());
 | 
			
		||||
  currentDateTime += std::chrono::seconds(dateTimeController.Seconds() + currentDeltaSeconds);
 | 
			
		||||
 | 
			
		||||
  currentDateTime -= std::chrono::hours(3); // TODO WHYYYY?
 | 
			
		||||
 | 
			
		||||
  auto dp = date::floor<date::days>(currentDateTime);
 | 
			
		||||
  auto time = date::make_time(currentDateTime-dp);
 | 
			
		||||
  auto ymd = date::year_month_day(dp);
 | 
			
		||||
 | 
			
		||||
  auto year = (int)ymd.year();
 | 
			
		||||
  auto month = (unsigned)ymd.month();
 | 
			
		||||
  auto day = (unsigned)ymd.day();
 | 
			
		||||
  auto weekday = date::weekday(ymd);
 | 
			
		||||
 | 
			
		||||
  auto hh = time.hours().count();
 | 
			
		||||
  auto mm = time.minutes().count();
 | 
			
		||||
  auto ss = time.seconds().count();
 | 
			
		||||
 | 
			
		||||
  char minutesChar[3];
 | 
			
		||||
  sprintf(minutesChar, "%02d", currentMinutes);
 | 
			
		||||
  sprintf(minutesChar, "%02d", mm);
 | 
			
		||||
 | 
			
		||||
  char hoursChar[3];
 | 
			
		||||
  sprintf(hoursChar, "%02d", currentHours);
 | 
			
		||||
  sprintf(hoursChar, "%02d", hh);
 | 
			
		||||
 | 
			
		||||
  uint8_t x = 7;
 | 
			
		||||
  if (hoursChar[0] != currentChar[0]) {
 | 
			
		||||
@ -218,16 +238,13 @@ void DisplayApp::RunningState() {
 | 
			
		||||
    currentChar[3] = minutesChar[1];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (dateUpdated) {
 | 
			
		||||
    auto year = dateTimeController.Year();
 | 
			
		||||
    auto month = dateTimeController.Month();
 | 
			
		||||
    auto day = dateTimeController.Day();
 | 
			
		||||
    auto dayOfWeek = dateTimeController.DayOfWeek();
 | 
			
		||||
 | 
			
		||||
  if (ymd != currentYmd) {
 | 
			
		||||
    gfx->FillRectangle(0,180, 240, 15, 0x0000);
 | 
			
		||||
    char dateStr[22];
 | 
			
		||||
    sprintf(dateStr, "%s %d %s %d", DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);
 | 
			
		||||
    sprintf(dateStr, "%s %d %s %d", DayOfWeekToString(Pinetime::Controllers::DateTime::Days(weekday.iso_encoding())), day, MonthToString((Pinetime::Controllers::DateTime::Months )month), year);
 | 
			
		||||
    gfx->DrawString(10, 180, 0xffff, dateStr, &smallFont, false);
 | 
			
		||||
    dateUpdated = false;
 | 
			
		||||
 | 
			
		||||
    currentYmd = ymd;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -11,6 +11,7 @@
 | 
			
		||||
#include <Components/DateTime/DateTimeController.h>
 | 
			
		||||
#include "lcdfont14.h"
 | 
			
		||||
#include "../drivers/Cst816s.h"
 | 
			
		||||
#include <date/date.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
extern const FONT_INFO lCD_70ptFontInfo;
 | 
			
		||||
@ -40,11 +41,10 @@ namespace Pinetime {
 | 
			
		||||
 | 
			
		||||
        static const char* MonthToString(Pinetime::Controllers::DateTime::Months month);
 | 
			
		||||
        static const char* DayOfWeekToString(Pinetime::Controllers::DateTime::Days dayOfWeek);
 | 
			
		||||
        uint8_t seconds = 0;
 | 
			
		||||
        uint8_t minutes = 0;
 | 
			
		||||
        uint8_t hours = 0;
 | 
			
		||||
 | 
			
		||||
        char currentChar[4];
 | 
			
		||||
        uint32_t deltaSeconds = 0;
 | 
			
		||||
        date::year_month_day currentYmd;
 | 
			
		||||
 | 
			
		||||
        States state = States::Running;
 | 
			
		||||
        void RunningState();
 | 
			
		||||
@ -62,7 +62,6 @@ namespace Pinetime {
 | 
			
		||||
 | 
			
		||||
        static char const *DaysString[];
 | 
			
		||||
        static char const *MonthsString[];
 | 
			
		||||
        bool dateUpdated = false;
 | 
			
		||||
 | 
			
		||||
        Pinetime::Drivers::Cst816S touchPanel;
 | 
			
		||||
        void OnTouchEvent();
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										34
									
								
								src/libs/date/includes/date/chrono_io.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/libs/date/includes/date/chrono_io.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,34 @@
 | 
			
		||||
#ifndef CHRONO_IO_H
 | 
			
		||||
#define CHRONO_IO_H
 | 
			
		||||
 | 
			
		||||
// The MIT License (MIT)
 | 
			
		||||
//
 | 
			
		||||
// Copyright (c) 2016, 2017 Howard Hinnant
 | 
			
		||||
//
 | 
			
		||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
// of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
// in the Software without restriction, including without limitation the rights
 | 
			
		||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
// copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
// furnished to do so, subject to the following conditions:
 | 
			
		||||
//
 | 
			
		||||
// The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
// copies or substantial portions of the Software.
 | 
			
		||||
//
 | 
			
		||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
// SOFTWARE.
 | 
			
		||||
//
 | 
			
		||||
// Our apologies.  When the previous paragraph was written, lowercase had not yet
 | 
			
		||||
// been invented (that would involve another several millennia of evolution).
 | 
			
		||||
// We did not mean to shout.
 | 
			
		||||
 | 
			
		||||
// This functionality has moved to "date.h"
 | 
			
		||||
 | 
			
		||||
#include "date.h"
 | 
			
		||||
 | 
			
		||||
#endif  // CHRONO_IO_H
 | 
			
		||||
							
								
								
									
										7947
									
								
								src/libs/date/includes/date/date.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7947
									
								
								src/libs/date/includes/date/date.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										50
									
								
								src/libs/date/includes/date/ios.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								src/libs/date/includes/date/ios.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,50 @@
 | 
			
		||||
//
 | 
			
		||||
//  ios.h
 | 
			
		||||
//  DateTimeLib
 | 
			
		||||
//
 | 
			
		||||
// The MIT License (MIT)
 | 
			
		||||
//
 | 
			
		||||
// Copyright (c) 2016 Alexander Kormanovsky
 | 
			
		||||
//
 | 
			
		||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
// of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
// in the Software without restriction, including without limitation the rights
 | 
			
		||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
// copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
// furnished to do so, subject to the following conditions:
 | 
			
		||||
//
 | 
			
		||||
// The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
// copies or substantial portions of the Software.
 | 
			
		||||
//
 | 
			
		||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
// SOFTWARE.
 | 
			
		||||
 | 
			
		||||
#ifndef ios_hpp
 | 
			
		||||
#define ios_hpp
 | 
			
		||||
 | 
			
		||||
#if __APPLE__
 | 
			
		||||
# include <TargetConditionals.h>
 | 
			
		||||
# if TARGET_OS_IPHONE
 | 
			
		||||
#   include <string>
 | 
			
		||||
 | 
			
		||||
    namespace date
 | 
			
		||||
    {
 | 
			
		||||
    namespace iOSUtils
 | 
			
		||||
    {
 | 
			
		||||
    
 | 
			
		||||
    std::string get_tzdata_path();
 | 
			
		||||
    std::string get_current_timezone();
 | 
			
		||||
    
 | 
			
		||||
    }  // namespace iOSUtils
 | 
			
		||||
    }  // namespace date
 | 
			
		||||
 | 
			
		||||
# endif  // TARGET_OS_IPHONE
 | 
			
		||||
#else   // !__APPLE__
 | 
			
		||||
# define TARGET_OS_IPHONE 0
 | 
			
		||||
#endif  // !__APPLE__
 | 
			
		||||
#endif // ios_hpp
 | 
			
		||||
							
								
								
									
										3031
									
								
								src/libs/date/includes/date/islamic.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3031
									
								
								src/libs/date/includes/date/islamic.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1751
									
								
								src/libs/date/includes/date/iso_week.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1751
									
								
								src/libs/date/includes/date/iso_week.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										3046
									
								
								src/libs/date/includes/date/julian.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3046
									
								
								src/libs/date/includes/date/julian.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										627
									
								
								src/libs/date/includes/date/ptz.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										627
									
								
								src/libs/date/includes/date/ptz.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,627 @@
 | 
			
		||||
#ifndef PTZ_H
 | 
			
		||||
#define PTZ_H
 | 
			
		||||
 | 
			
		||||
// The MIT License (MIT)
 | 
			
		||||
//
 | 
			
		||||
// Copyright (c) 2017 Howard Hinnant
 | 
			
		||||
//
 | 
			
		||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
// of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
// in the Software without restriction, including without limitation the rights
 | 
			
		||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
// copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
// furnished to do so, subject to the following conditions:
 | 
			
		||||
//
 | 
			
		||||
// The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
// copies or substantial portions of the Software.
 | 
			
		||||
//
 | 
			
		||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
// SOFTWARE.
 | 
			
		||||
 | 
			
		||||
// This header allows Posix-style time zones as specified for TZ here:
 | 
			
		||||
// http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03
 | 
			
		||||
//
 | 
			
		||||
// Posix::time_zone can be constructed with a posix-style string and then used in
 | 
			
		||||
// a zoned_time like so:
 | 
			
		||||
//
 | 
			
		||||
// zoned_time<system_clock::duration, Posix::time_zone> zt{"EST5EDT,M3.2.0,M11.1.0",
 | 
			
		||||
//                                                         system_clock::now()};
 | 
			
		||||
// or:
 | 
			
		||||
//
 | 
			
		||||
// Posix::time_zone tz{"EST5EDT,M3.2.0,M11.1.0"};
 | 
			
		||||
// zoned_time<system_clock::duration, Posix::time_zone> zt{tz, system_clock::now()};
 | 
			
		||||
//
 | 
			
		||||
// Note, Posix-style time zones are not recommended for all of the reasons described here:
 | 
			
		||||
// https://stackoverflow.com/tags/timezone/info
 | 
			
		||||
//
 | 
			
		||||
// They are provided here as a non-trivial custom time zone example, and if you really
 | 
			
		||||
// have to have Posix time zones, you're welcome to use this one.
 | 
			
		||||
 | 
			
		||||
#include "date/tz.h"
 | 
			
		||||
#include <cctype>
 | 
			
		||||
#include <ostream>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
namespace Posix
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
namespace detail
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
#if HAS_STRING_VIEW
 | 
			
		||||
 | 
			
		||||
using string_t = std::string_view;
 | 
			
		||||
 | 
			
		||||
#else  // !HAS_STRING_VIEW
 | 
			
		||||
 | 
			
		||||
using string_t = std::string;
 | 
			
		||||
 | 
			
		||||
#endif  // !HAS_STRING_VIEW
 | 
			
		||||
 | 
			
		||||
class rule;
 | 
			
		||||
 | 
			
		||||
void throw_invalid(const string_t& s, unsigned i, const string_t& message);
 | 
			
		||||
unsigned read_date(const string_t& s, unsigned i, rule& r);
 | 
			
		||||
unsigned read_name(const string_t& s, unsigned i, std::string& name);
 | 
			
		||||
unsigned read_signed_time(const string_t& s, unsigned i, std::chrono::seconds& t);
 | 
			
		||||
unsigned read_unsigned_time(const string_t& s, unsigned i, std::chrono::seconds& t);
 | 
			
		||||
unsigned read_unsigned(const string_t& s, unsigned i,  unsigned limit, unsigned& u);
 | 
			
		||||
 | 
			
		||||
class rule
 | 
			
		||||
{
 | 
			
		||||
    enum {off, J, M, N};
 | 
			
		||||
 | 
			
		||||
    date::month m_;
 | 
			
		||||
    date::weekday wd_;
 | 
			
		||||
    unsigned short n_    : 14;
 | 
			
		||||
    unsigned short mode_ : 2;
 | 
			
		||||
    std::chrono::duration<std::int32_t> time_ = std::chrono::hours{2};
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    rule() : mode_(off) {}
 | 
			
		||||
 | 
			
		||||
    bool ok() const {return mode_ != off;}
 | 
			
		||||
    date::local_seconds operator()(date::year y) const;
 | 
			
		||||
 | 
			
		||||
    friend std::ostream& operator<<(std::ostream& os, const rule& r);
 | 
			
		||||
    friend unsigned read_date(const string_t& s, unsigned i, rule& r);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
date::local_seconds
 | 
			
		||||
rule::operator()(date::year y) const
 | 
			
		||||
{
 | 
			
		||||
    using date::local_days;
 | 
			
		||||
    using date::January;
 | 
			
		||||
    using date::days;
 | 
			
		||||
    using date::last;
 | 
			
		||||
    using sec = std::chrono::seconds;
 | 
			
		||||
    date::local_seconds t;
 | 
			
		||||
    switch (mode_)
 | 
			
		||||
    {
 | 
			
		||||
    case J:
 | 
			
		||||
        t = local_days{y/January/0} + days{n_ + (y.is_leap() && n_ > 59)} + sec{time_};
 | 
			
		||||
        break;
 | 
			
		||||
    case M:
 | 
			
		||||
        t = (n_ == 5 ? local_days{y/m_/wd_[last]} : local_days{y/m_/wd_[n_]}) + sec{time_};
 | 
			
		||||
        break;
 | 
			
		||||
    case N:
 | 
			
		||||
        t = local_days{y/January/1} + days{n_} + sec{time_};
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        assert(!"rule called with bad mode");
 | 
			
		||||
    }
 | 
			
		||||
    return t;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
std::ostream&
 | 
			
		||||
operator<<(std::ostream& os, const rule& r)
 | 
			
		||||
{
 | 
			
		||||
    switch (r.mode_)
 | 
			
		||||
    {
 | 
			
		||||
    case rule::J:
 | 
			
		||||
        os << 'J' << r.n_ << date::format(" %T", r.time_);
 | 
			
		||||
        break;
 | 
			
		||||
    case rule::M:
 | 
			
		||||
        if (r.n_ == 5)
 | 
			
		||||
            os << r.m_/r.wd_[date::last];
 | 
			
		||||
        else
 | 
			
		||||
            os << r.m_/r.wd_[r.n_];
 | 
			
		||||
        os <<  date::format(" %T", r.time_);
 | 
			
		||||
        break;
 | 
			
		||||
    case rule::N:
 | 
			
		||||
        os << r.n_ << date::format(" %T", r.time_);
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    return os;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace detail
 | 
			
		||||
 | 
			
		||||
class time_zone
 | 
			
		||||
{
 | 
			
		||||
    std::string          std_abbrev_;
 | 
			
		||||
    std::string          dst_abbrev_ = {};
 | 
			
		||||
    std::chrono::seconds offset_;
 | 
			
		||||
    std::chrono::seconds save_ = std::chrono::hours{1};
 | 
			
		||||
    detail::rule         start_rule_;
 | 
			
		||||
    detail::rule         end_rule_;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    explicit time_zone(const detail::string_t& name);
 | 
			
		||||
 | 
			
		||||
    template <class Duration>
 | 
			
		||||
        date::sys_info   get_info(date::sys_time<Duration> st) const;
 | 
			
		||||
    template <class Duration>
 | 
			
		||||
        date::local_info get_info(date::local_time<Duration> tp) const;
 | 
			
		||||
 | 
			
		||||
    template <class Duration>
 | 
			
		||||
        date::sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
 | 
			
		||||
        to_sys(date::local_time<Duration> tp) const;
 | 
			
		||||
 | 
			
		||||
    template <class Duration>
 | 
			
		||||
        date::sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
 | 
			
		||||
        to_sys(date::local_time<Duration> tp, date::choose z) const;
 | 
			
		||||
 | 
			
		||||
    template <class Duration>
 | 
			
		||||
        date::local_time<typename std::common_type<Duration, std::chrono::seconds>::type>
 | 
			
		||||
        to_local(date::sys_time<Duration> tp) const;
 | 
			
		||||
 | 
			
		||||
    friend std::ostream& operator<<(std::ostream& os, const time_zone& z);
 | 
			
		||||
 | 
			
		||||
    const time_zone* operator->() const {return this;}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
time_zone::time_zone(const detail::string_t& s)
 | 
			
		||||
{
 | 
			
		||||
    using detail::read_name;
 | 
			
		||||
    using detail::read_signed_time;
 | 
			
		||||
    using detail::throw_invalid;
 | 
			
		||||
    auto i = read_name(s, 0, std_abbrev_);
 | 
			
		||||
    i = read_signed_time(s, i, offset_);
 | 
			
		||||
    offset_ = -offset_;
 | 
			
		||||
    if (i != s.size())
 | 
			
		||||
    {
 | 
			
		||||
        i = read_name(s, i, dst_abbrev_);
 | 
			
		||||
        if (i != s.size())
 | 
			
		||||
        {
 | 
			
		||||
            if (s[i] != ',')
 | 
			
		||||
                i = read_signed_time(s, i, save_);
 | 
			
		||||
            if (i != s.size())
 | 
			
		||||
            {
 | 
			
		||||
                if (s[i] != ',')
 | 
			
		||||
                    throw_invalid(s, i, "Expecting end of string or ',' to start rule");
 | 
			
		||||
                ++i;
 | 
			
		||||
                i = read_date(s, i, start_rule_);
 | 
			
		||||
                if (i == s.size() || s[i] != ',')
 | 
			
		||||
                    throw_invalid(s, i, "Expecting ',' and then the ending rule");
 | 
			
		||||
                ++i;
 | 
			
		||||
                i = read_date(s, i, end_rule_);
 | 
			
		||||
                if (i != s.size())
 | 
			
		||||
                    throw_invalid(s, i, "Found unexpected trailing characters");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class Duration>
 | 
			
		||||
date::sys_info
 | 
			
		||||
time_zone::get_info(date::sys_time<Duration> st) const
 | 
			
		||||
{
 | 
			
		||||
    using date::sys_info;
 | 
			
		||||
    using date::year_month_day;
 | 
			
		||||
    using date::sys_seconds;
 | 
			
		||||
    using date::sys_days;
 | 
			
		||||
    using date::floor;
 | 
			
		||||
    using date::ceil;
 | 
			
		||||
    using date::days;
 | 
			
		||||
    using date::years;
 | 
			
		||||
    using date::year;
 | 
			
		||||
    using date::January;
 | 
			
		||||
    using date::December;
 | 
			
		||||
    using date::last;
 | 
			
		||||
    using std::chrono::minutes;
 | 
			
		||||
    sys_info r{};
 | 
			
		||||
    r.offset = offset_;
 | 
			
		||||
    if (start_rule_.ok())
 | 
			
		||||
    {
 | 
			
		||||
        auto y = year_month_day{floor<days>(st)}.year();
 | 
			
		||||
        auto start = sys_seconds{(start_rule_(y) - offset_).time_since_epoch()};
 | 
			
		||||
        auto end   = sys_seconds{(end_rule_(y) - (offset_ + save_)).time_since_epoch()};
 | 
			
		||||
        if (start <= st && st < end)
 | 
			
		||||
        {
 | 
			
		||||
            r.begin = start;
 | 
			
		||||
            r.end = end;
 | 
			
		||||
            r.offset += save_;
 | 
			
		||||
            r.save = ceil<minutes>(save_);
 | 
			
		||||
            r.abbrev = dst_abbrev_;
 | 
			
		||||
        }
 | 
			
		||||
        else if (st < start)
 | 
			
		||||
        {
 | 
			
		||||
            r.begin = sys_seconds{(end_rule_(y-years{1}) -
 | 
			
		||||
                                   (offset_ + save_)).time_since_epoch()};
 | 
			
		||||
            r.end = start;
 | 
			
		||||
            r.abbrev = std_abbrev_;
 | 
			
		||||
        }
 | 
			
		||||
        else  // st >= end
 | 
			
		||||
        {
 | 
			
		||||
            r.begin = end;
 | 
			
		||||
            r.end = sys_seconds{(start_rule_(y+years{1}) - offset_).time_since_epoch()};
 | 
			
		||||
            r.abbrev = std_abbrev_;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else  //  constant offset
 | 
			
		||||
    {
 | 
			
		||||
        r.begin = sys_days{year::min()/January/1};
 | 
			
		||||
        r.end   = sys_days{year::max()/December/last};
 | 
			
		||||
        r.abbrev = std_abbrev_;
 | 
			
		||||
    }
 | 
			
		||||
    return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class Duration>
 | 
			
		||||
date::local_info
 | 
			
		||||
time_zone::get_info(date::local_time<Duration> tp) const
 | 
			
		||||
{
 | 
			
		||||
    using date::local_info;
 | 
			
		||||
    using date::year_month_day;
 | 
			
		||||
    using date::days;
 | 
			
		||||
    using date::sys_days;
 | 
			
		||||
    using date::sys_seconds;
 | 
			
		||||
    using date::years;
 | 
			
		||||
    using date::year;
 | 
			
		||||
    using date::ceil;
 | 
			
		||||
    using date::January;
 | 
			
		||||
    using date::December;
 | 
			
		||||
    using date::last;
 | 
			
		||||
    using std::chrono::seconds;
 | 
			
		||||
    using std::chrono::minutes;
 | 
			
		||||
    local_info r{};
 | 
			
		||||
    using date::floor;
 | 
			
		||||
    if (start_rule_.ok())
 | 
			
		||||
    {
 | 
			
		||||
        auto y = year_month_day{floor<days>(tp)}.year();
 | 
			
		||||
        auto start = sys_seconds{(start_rule_(y) - offset_).time_since_epoch()};
 | 
			
		||||
        auto end   = sys_seconds{(end_rule_(y) - (offset_ + save_)).time_since_epoch()};
 | 
			
		||||
        auto utcs = sys_seconds{floor<seconds>(tp - offset_).time_since_epoch()};
 | 
			
		||||
        auto utcd = sys_seconds{floor<seconds>(tp - (offset_ + save_)).time_since_epoch()};
 | 
			
		||||
        if ((utcs < start) != (utcd < start))
 | 
			
		||||
        {
 | 
			
		||||
            r.first.begin = sys_seconds{(end_rule_(y-years{1}) -
 | 
			
		||||
                                         (offset_ + save_)).time_since_epoch()};
 | 
			
		||||
            r.first.end = start;
 | 
			
		||||
            r.first.offset = offset_;
 | 
			
		||||
            r.first.abbrev = std_abbrev_;
 | 
			
		||||
            r.second.begin = start;
 | 
			
		||||
            r.second.end = end;
 | 
			
		||||
            r.second.abbrev = dst_abbrev_;
 | 
			
		||||
            r.second.offset = offset_ + save_;
 | 
			
		||||
            r.second.save = ceil<minutes>(save_);
 | 
			
		||||
            r.result = save_ > seconds{0} ? local_info::nonexistent
 | 
			
		||||
                                          : local_info::ambiguous;
 | 
			
		||||
        }
 | 
			
		||||
        else if ((utcs < end) != (utcd < end))
 | 
			
		||||
        {
 | 
			
		||||
            r.first.begin = start;
 | 
			
		||||
            r.first.end = end;
 | 
			
		||||
            r.first.offset = offset_ + save_;
 | 
			
		||||
            r.first.save = ceil<minutes>(save_);
 | 
			
		||||
            r.first.abbrev = dst_abbrev_;
 | 
			
		||||
            r.second.begin = end;
 | 
			
		||||
            r.second.end = sys_seconds{(start_rule_(y+years{1}) -
 | 
			
		||||
                                        offset_).time_since_epoch()};
 | 
			
		||||
            r.second.abbrev = std_abbrev_;
 | 
			
		||||
            r.second.offset = offset_;
 | 
			
		||||
            r.result = save_ > seconds{0} ? local_info::ambiguous
 | 
			
		||||
                                          : local_info::nonexistent;
 | 
			
		||||
        }
 | 
			
		||||
        else if (utcs < start)
 | 
			
		||||
        {
 | 
			
		||||
            r.first.begin = sys_seconds{(end_rule_(y-years{1}) -
 | 
			
		||||
                                   (offset_ + save_)).time_since_epoch()};
 | 
			
		||||
            r.first.end = start;
 | 
			
		||||
            r.first.offset = offset_;
 | 
			
		||||
            r.first.abbrev = std_abbrev_;
 | 
			
		||||
        }
 | 
			
		||||
        else if (utcs < end)
 | 
			
		||||
        {
 | 
			
		||||
            r.first.begin = start;
 | 
			
		||||
            r.first.end = end;
 | 
			
		||||
            r.first.offset = offset_ + save_;
 | 
			
		||||
            r.first.save = ceil<minutes>(save_);
 | 
			
		||||
            r.first.abbrev = dst_abbrev_;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            r.first.begin = end;
 | 
			
		||||
            r.first.end = sys_seconds{(start_rule_(y+years{1}) -
 | 
			
		||||
                                       offset_).time_since_epoch()};
 | 
			
		||||
            r.first.abbrev = std_abbrev_;
 | 
			
		||||
            r.first.offset = offset_;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else  //  constant offset
 | 
			
		||||
    {
 | 
			
		||||
        r.first.begin = sys_days{year::min()/January/1};
 | 
			
		||||
        r.first.end   = sys_days{year::max()/December/last};
 | 
			
		||||
        r.first.abbrev = std_abbrev_;
 | 
			
		||||
        r.first.offset = offset_;
 | 
			
		||||
    }
 | 
			
		||||
    return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class Duration>
 | 
			
		||||
date::sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
 | 
			
		||||
time_zone::to_sys(date::local_time<Duration> tp) const
 | 
			
		||||
{
 | 
			
		||||
    using date::local_info;
 | 
			
		||||
    using date::sys_time;
 | 
			
		||||
    using date::ambiguous_local_time;
 | 
			
		||||
    auto i = get_info(tp);
 | 
			
		||||
    if (i.result == local_info::nonexistent)
 | 
			
		||||
        throw nonexistent_local_time(tp, i);
 | 
			
		||||
    else if (i.result == local_info::ambiguous)
 | 
			
		||||
        throw ambiguous_local_time(tp, i);
 | 
			
		||||
    return sys_time<Duration>{tp.time_since_epoch()} - i.first.offset;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class Duration>
 | 
			
		||||
date::sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
 | 
			
		||||
time_zone::to_sys(date::local_time<Duration> tp, date::choose z) const
 | 
			
		||||
{
 | 
			
		||||
    using date::local_info;
 | 
			
		||||
    using date::sys_time;
 | 
			
		||||
    using date::choose;
 | 
			
		||||
    auto i = get_info(tp);
 | 
			
		||||
    if (i.result == local_info::nonexistent)
 | 
			
		||||
    {
 | 
			
		||||
        return i.first.end;
 | 
			
		||||
    }
 | 
			
		||||
    else if (i.result == local_info::ambiguous)
 | 
			
		||||
    {
 | 
			
		||||
        if (z == choose::latest)
 | 
			
		||||
            return sys_time<Duration>{tp.time_since_epoch()} - i.second.offset;
 | 
			
		||||
    }
 | 
			
		||||
    return sys_time<Duration>{tp.time_since_epoch()} - i.first.offset;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class Duration>
 | 
			
		||||
date::local_time<typename std::common_type<Duration, std::chrono::seconds>::type>
 | 
			
		||||
time_zone::to_local(date::sys_time<Duration> tp) const
 | 
			
		||||
{
 | 
			
		||||
    using date::local_time;
 | 
			
		||||
    using std::chrono::seconds;
 | 
			
		||||
    using LT = local_time<typename std::common_type<Duration, seconds>::type>;
 | 
			
		||||
    auto i = get_info(tp);
 | 
			
		||||
    return LT{(tp + i.offset).time_since_epoch()};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
std::ostream&
 | 
			
		||||
operator<<(std::ostream& os, const time_zone& z)
 | 
			
		||||
{
 | 
			
		||||
    using date::operator<<;
 | 
			
		||||
    os << '{';
 | 
			
		||||
    os << z.std_abbrev_ << ", " << z.dst_abbrev_ << date::format(", %T, ", z.offset_)
 | 
			
		||||
       << date::format("%T, [", z.save_) << z.start_rule_ << ", " << z.end_rule_ << ")}";
 | 
			
		||||
    return os;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace detail
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
void
 | 
			
		||||
throw_invalid(const string_t& s, unsigned i, const string_t& message)
 | 
			
		||||
{
 | 
			
		||||
    throw std::runtime_error(std::string("Invalid time_zone initializer.\n") +
 | 
			
		||||
                             std::string(message) + ":\n" +
 | 
			
		||||
                             std::string(s) + '\n' +
 | 
			
		||||
                             "\x1b[1;32m" +
 | 
			
		||||
                             std::string(i, '~') + '^' +
 | 
			
		||||
                             std::string(s.size()-i-1, '~') +
 | 
			
		||||
                             "\x1b[0m");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
unsigned
 | 
			
		||||
read_date(const string_t& s, unsigned i, rule& r)
 | 
			
		||||
{
 | 
			
		||||
    using date::month;
 | 
			
		||||
    using date::weekday;
 | 
			
		||||
    if (i == s.size())
 | 
			
		||||
        throw_invalid(s, i, "Expected rule but found end of string");
 | 
			
		||||
    if (s[i] == 'J')
 | 
			
		||||
    {
 | 
			
		||||
        ++i;
 | 
			
		||||
        unsigned n;
 | 
			
		||||
        i = read_unsigned(s, i, 3, n);
 | 
			
		||||
        r.mode_ = rule::J;
 | 
			
		||||
        r.n_ = n;
 | 
			
		||||
    }
 | 
			
		||||
    else if (s[i] == 'M')
 | 
			
		||||
    {
 | 
			
		||||
        ++i;
 | 
			
		||||
        unsigned m;
 | 
			
		||||
        i = read_unsigned(s, i, 2, m);
 | 
			
		||||
        if (i == s.size() || s[i] != '.')
 | 
			
		||||
            throw_invalid(s, i, "Expected '.' after month");
 | 
			
		||||
        ++i;
 | 
			
		||||
        unsigned n;
 | 
			
		||||
        i = read_unsigned(s, i, 1, n);
 | 
			
		||||
        if (i == s.size() || s[i] != '.')
 | 
			
		||||
            throw_invalid(s, i, "Expected '.' after weekday index");
 | 
			
		||||
        ++i;
 | 
			
		||||
        unsigned wd;
 | 
			
		||||
        i = read_unsigned(s, i, 1, wd);
 | 
			
		||||
        r.mode_ = rule::M;
 | 
			
		||||
        r.m_ = month{m};
 | 
			
		||||
        r.wd_ = weekday{wd};
 | 
			
		||||
        r.n_ = n;
 | 
			
		||||
    }
 | 
			
		||||
    else if (std::isdigit(s[i]))
 | 
			
		||||
    {
 | 
			
		||||
        unsigned n;
 | 
			
		||||
        i = read_unsigned(s, i, 3, n);
 | 
			
		||||
        r.mode_ = rule::N;
 | 
			
		||||
        r.n_ = n;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
        throw_invalid(s, i, "Expected 'J', 'M', or a digit to start rule");
 | 
			
		||||
    if (i != s.size() && s[i] == '/')
 | 
			
		||||
    {
 | 
			
		||||
        ++i;
 | 
			
		||||
        std::chrono::seconds t;
 | 
			
		||||
        i = read_unsigned_time(s, i, t);
 | 
			
		||||
        r.time_ = t;
 | 
			
		||||
    }
 | 
			
		||||
    return i;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
unsigned
 | 
			
		||||
read_name(const string_t& s, unsigned i, std::string& name)
 | 
			
		||||
{
 | 
			
		||||
    if (i == s.size())
 | 
			
		||||
        throw_invalid(s, i, "Expected a name but found end of string");
 | 
			
		||||
    if (s[i] == '<')
 | 
			
		||||
    {
 | 
			
		||||
        ++i;
 | 
			
		||||
        while (true)
 | 
			
		||||
        {
 | 
			
		||||
            if (i == s.size())
 | 
			
		||||
                throw_invalid(s, i,
 | 
			
		||||
                              "Expected to find closing '>', but found end of string");
 | 
			
		||||
            if (s[i] == '>')
 | 
			
		||||
                break;
 | 
			
		||||
            name.push_back(s[i]);
 | 
			
		||||
            ++i;
 | 
			
		||||
        }
 | 
			
		||||
        ++i;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        while (i != s.size() && std::isalpha(s[i]))
 | 
			
		||||
        {
 | 
			
		||||
            name.push_back(s[i]);
 | 
			
		||||
            ++i;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (name.size() < 3)
 | 
			
		||||
        throw_invalid(s, i, "Found name to be shorter than 3 characters");
 | 
			
		||||
    return i;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
unsigned
 | 
			
		||||
read_signed_time(const string_t& s, unsigned i,
 | 
			
		||||
                                  std::chrono::seconds& t)
 | 
			
		||||
{
 | 
			
		||||
    if (i == s.size())
 | 
			
		||||
        throw_invalid(s, i, "Expected to read signed time, but found end of string");
 | 
			
		||||
    bool negative = false;
 | 
			
		||||
    if (s[i] == '-')
 | 
			
		||||
    {
 | 
			
		||||
        negative = true;
 | 
			
		||||
        ++i;
 | 
			
		||||
    }
 | 
			
		||||
    else if (s[i] == '+')
 | 
			
		||||
        ++i;
 | 
			
		||||
    i = read_unsigned_time(s, i, t);
 | 
			
		||||
    if (negative)
 | 
			
		||||
        t = -t;
 | 
			
		||||
    return i;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
unsigned
 | 
			
		||||
read_unsigned_time(const string_t& s, unsigned i, std::chrono::seconds& t)
 | 
			
		||||
{
 | 
			
		||||
    using std::chrono::seconds;
 | 
			
		||||
    using std::chrono::minutes;
 | 
			
		||||
    using std::chrono::hours;
 | 
			
		||||
    if (i == s.size())
 | 
			
		||||
        throw_invalid(s, i, "Expected to read unsigned time, but found end of string");
 | 
			
		||||
    unsigned x;
 | 
			
		||||
    i = read_unsigned(s, i, 2, x);
 | 
			
		||||
    t = hours{x};
 | 
			
		||||
    if (i != s.size() && s[i] == ':')
 | 
			
		||||
    {
 | 
			
		||||
        ++i;
 | 
			
		||||
        i = read_unsigned(s, i, 2, x);
 | 
			
		||||
        t += minutes{x};
 | 
			
		||||
        if (i != s.size() && s[i] == ':')
 | 
			
		||||
        {
 | 
			
		||||
            ++i;
 | 
			
		||||
            i = read_unsigned(s, i, 2, x);
 | 
			
		||||
            t += seconds{x};
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return i;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
unsigned
 | 
			
		||||
read_unsigned(const string_t& s, unsigned i, unsigned limit, unsigned& u)
 | 
			
		||||
{
 | 
			
		||||
    if (i == s.size() || !std::isdigit(s[i]))
 | 
			
		||||
        throw_invalid(s, i, "Expected to find a decimal digit");
 | 
			
		||||
    u = static_cast<unsigned>(s[i] - '0');
 | 
			
		||||
    unsigned count = 1;
 | 
			
		||||
    for (++i; count < limit && i != s.size() && std::isdigit(s[i]); ++i, ++count)
 | 
			
		||||
        u = u * 10 + static_cast<unsigned>(s[i] - '0');
 | 
			
		||||
    return i;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace detail
 | 
			
		||||
 | 
			
		||||
}  // namespace Posix
 | 
			
		||||
 | 
			
		||||
namespace date
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
struct zoned_traits<Posix::time_zone>
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
#if HAS_STRING_VIEW
 | 
			
		||||
 | 
			
		||||
    static
 | 
			
		||||
    Posix::time_zone
 | 
			
		||||
    locate_zone(std::string_view name)
 | 
			
		||||
    {
 | 
			
		||||
        return Posix::time_zone{name};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#else  // !HAS_STRING_VIEW
 | 
			
		||||
 | 
			
		||||
    static
 | 
			
		||||
    Posix::time_zone
 | 
			
		||||
    locate_zone(const std::string& name)
 | 
			
		||||
    {
 | 
			
		||||
        return Posix::time_zone{name};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static
 | 
			
		||||
    Posix::time_zone
 | 
			
		||||
    locate_zone(const char* name)
 | 
			
		||||
    {
 | 
			
		||||
        return Posix::time_zone{name};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#endif  // !HAS_STRING_VIEW
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace date
 | 
			
		||||
 | 
			
		||||
#endif  // PTZ_H
 | 
			
		||||
							
								
								
									
										2775
									
								
								src/libs/date/includes/date/tz.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2775
									
								
								src/libs/date/includes/date/tz.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										316
									
								
								src/libs/date/includes/date/tz_private.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										316
									
								
								src/libs/date/includes/date/tz_private.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,316 @@
 | 
			
		||||
#ifndef TZ_PRIVATE_H
 | 
			
		||||
#define TZ_PRIVATE_H
 | 
			
		||||
 | 
			
		||||
// The MIT License (MIT)
 | 
			
		||||
//
 | 
			
		||||
// Copyright (c) 2015, 2016 Howard Hinnant
 | 
			
		||||
//
 | 
			
		||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
// of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
// in the Software without restriction, including without limitation the rights
 | 
			
		||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
// copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
// furnished to do so, subject to the following conditions:
 | 
			
		||||
//
 | 
			
		||||
// The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
// copies or substantial portions of the Software.
 | 
			
		||||
//
 | 
			
		||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
// SOFTWARE.
 | 
			
		||||
//
 | 
			
		||||
// Our apologies.  When the previous paragraph was written, lowercase had not yet
 | 
			
		||||
// been invented (that would involve another several millennia of evolution).
 | 
			
		||||
// We did not mean to shout.
 | 
			
		||||
 | 
			
		||||
#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
 | 
			
		||||
#include "tz.h"
 | 
			
		||||
#else
 | 
			
		||||
#include "date.h"
 | 
			
		||||
#include <vector>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
namespace date
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
namespace detail
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
#if !USE_OS_TZDB
 | 
			
		||||
 | 
			
		||||
enum class tz {utc, local, standard};
 | 
			
		||||
 | 
			
		||||
//forward declare to avoid warnings in gcc 6.2
 | 
			
		||||
class MonthDayTime;
 | 
			
		||||
std::istream& operator>>(std::istream& is, MonthDayTime& x);
 | 
			
		||||
std::ostream& operator<<(std::ostream& os, const MonthDayTime& x);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MonthDayTime
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
    struct pair
 | 
			
		||||
    {
 | 
			
		||||
#if defined(_MSC_VER) && (_MSC_VER < 1900)
 | 
			
		||||
        pair() : month_day_(date::jan / 1), weekday_(0U) {}
 | 
			
		||||
 | 
			
		||||
        pair(const date::month_day& month_day, const date::weekday& weekday)
 | 
			
		||||
            : month_day_(month_day), weekday_(weekday) {}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        date::month_day month_day_;
 | 
			
		||||
        date::weekday   weekday_;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    enum Type {month_day, month_last_dow, lteq, gteq};
 | 
			
		||||
 | 
			
		||||
    Type                         type_{month_day};
 | 
			
		||||
 | 
			
		||||
#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
 | 
			
		||||
    union U
 | 
			
		||||
#else
 | 
			
		||||
    struct U
 | 
			
		||||
#endif
 | 
			
		||||
    {
 | 
			
		||||
        date::month_day          month_day_;
 | 
			
		||||
        date::month_weekday_last month_weekday_last_;
 | 
			
		||||
        pair                     month_day_weekday_;
 | 
			
		||||
 | 
			
		||||
#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
 | 
			
		||||
        U() : month_day_{date::jan/1} {}
 | 
			
		||||
#else
 | 
			
		||||
        U() :
 | 
			
		||||
            month_day_(date::jan/1),
 | 
			
		||||
            month_weekday_last_(date::month(0U), date::weekday_last(date::weekday(0U)))
 | 
			
		||||
        {}
 | 
			
		||||
 | 
			
		||||
#endif // !defined(_MSC_VER) || (_MSC_VER >= 1900)
 | 
			
		||||
 | 
			
		||||
        U& operator=(const date::month_day& x);
 | 
			
		||||
        U& operator=(const date::month_weekday_last& x);
 | 
			
		||||
        U& operator=(const pair& x);
 | 
			
		||||
    } u;
 | 
			
		||||
 | 
			
		||||
    std::chrono::hours           h_{};
 | 
			
		||||
    std::chrono::minutes         m_{};
 | 
			
		||||
    std::chrono::seconds         s_{};
 | 
			
		||||
    tz                           zone_{tz::local};
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    MonthDayTime() = default;
 | 
			
		||||
    MonthDayTime(local_seconds tp, tz timezone);
 | 
			
		||||
    MonthDayTime(const date::month_day& md, tz timezone);
 | 
			
		||||
 | 
			
		||||
    date::day day() const;
 | 
			
		||||
    date::month month() const;
 | 
			
		||||
    tz zone() const {return zone_;}
 | 
			
		||||
 | 
			
		||||
    void canonicalize(date::year y);
 | 
			
		||||
 | 
			
		||||
    sys_seconds
 | 
			
		||||
       to_sys(date::year y, std::chrono::seconds offset, std::chrono::seconds save) const;
 | 
			
		||||
    sys_days to_sys_days(date::year y) const;
 | 
			
		||||
 | 
			
		||||
    sys_seconds to_time_point(date::year y) const;
 | 
			
		||||
    int compare(date::year y, const MonthDayTime& x, date::year yx,
 | 
			
		||||
                std::chrono::seconds offset, std::chrono::minutes prev_save) const;
 | 
			
		||||
 | 
			
		||||
    friend std::istream& operator>>(std::istream& is, MonthDayTime& x);
 | 
			
		||||
    friend std::ostream& operator<<(std::ostream& os, const MonthDayTime& x);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// A Rule specifies one or more set of datetimes without using an offset.
 | 
			
		||||
// Multiple dates are specified with multiple years.  The years in effect
 | 
			
		||||
// go from starting_year_ to ending_year_, inclusive.  starting_year_ <=
 | 
			
		||||
// ending_year_. save_ is in effect for times from the specified time
 | 
			
		||||
// onward, including the specified time. When the specified time is
 | 
			
		||||
// local, it uses the save_ from the chronologically previous Rule, or if
 | 
			
		||||
// there is none, 0.
 | 
			
		||||
 | 
			
		||||
//forward declare to avoid warnings in gcc 6.2
 | 
			
		||||
class Rule;
 | 
			
		||||
bool operator==(const Rule& x, const Rule& y);
 | 
			
		||||
bool operator<(const Rule& x, const Rule& y);
 | 
			
		||||
bool operator==(const Rule& x, const date::year& y);
 | 
			
		||||
bool operator<(const Rule& x, const date::year& y);
 | 
			
		||||
bool operator==(const date::year& x, const Rule& y);
 | 
			
		||||
bool operator<(const date::year& x, const Rule& y);
 | 
			
		||||
bool operator==(const Rule& x, const std::string& y);
 | 
			
		||||
bool operator<(const Rule& x, const std::string& y);
 | 
			
		||||
bool operator==(const std::string& x, const Rule& y);
 | 
			
		||||
bool operator<(const std::string& x, const Rule& y);
 | 
			
		||||
std::ostream& operator<<(std::ostream& os, const Rule& r);
 | 
			
		||||
 | 
			
		||||
class Rule
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
    std::string          name_;
 | 
			
		||||
    date::year           starting_year_{0};
 | 
			
		||||
    date::year           ending_year_{0};
 | 
			
		||||
    MonthDayTime         starting_at_;
 | 
			
		||||
    std::chrono::minutes save_{0};
 | 
			
		||||
    std::string          abbrev_;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    Rule() = default;
 | 
			
		||||
    explicit Rule(const std::string& s);
 | 
			
		||||
    Rule(const Rule& r, date::year starting_year, date::year ending_year);
 | 
			
		||||
 | 
			
		||||
    const std::string& name() const {return name_;}
 | 
			
		||||
    const std::string& abbrev() const {return abbrev_;}
 | 
			
		||||
 | 
			
		||||
    const MonthDayTime&         mdt()           const {return starting_at_;}
 | 
			
		||||
    const date::year&           starting_year() const {return starting_year_;}
 | 
			
		||||
    const date::year&           ending_year()   const {return ending_year_;}
 | 
			
		||||
    const std::chrono::minutes& save()          const {return save_;}
 | 
			
		||||
 | 
			
		||||
    static void split_overlaps(std::vector<Rule>& rules);
 | 
			
		||||
 | 
			
		||||
    friend bool operator==(const Rule& x, const Rule& y);
 | 
			
		||||
    friend bool operator<(const Rule& x, const Rule& y);
 | 
			
		||||
    friend bool operator==(const Rule& x, const date::year& y);
 | 
			
		||||
    friend bool operator<(const Rule& x, const date::year& y);
 | 
			
		||||
    friend bool operator==(const date::year& x, const Rule& y);
 | 
			
		||||
    friend bool operator<(const date::year& x, const Rule& y);
 | 
			
		||||
    friend bool operator==(const Rule& x, const std::string& y);
 | 
			
		||||
    friend bool operator<(const Rule& x, const std::string& y);
 | 
			
		||||
    friend bool operator==(const std::string& x, const Rule& y);
 | 
			
		||||
    friend bool operator<(const std::string& x, const Rule& y);
 | 
			
		||||
 | 
			
		||||
    friend std::ostream& operator<<(std::ostream& os, const Rule& r);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    date::day day() const;
 | 
			
		||||
    date::month month() const;
 | 
			
		||||
    static void split_overlaps(std::vector<Rule>& rules, std::size_t i, std::size_t& e);
 | 
			
		||||
    static bool overlaps(const Rule& x, const Rule& y);
 | 
			
		||||
    static void split(std::vector<Rule>& rules, std::size_t i, std::size_t k,
 | 
			
		||||
                      std::size_t& e);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
inline bool operator!=(const Rule& x, const Rule& y) {return !(x == y);}
 | 
			
		||||
inline bool operator> (const Rule& x, const Rule& y) {return   y < x;}
 | 
			
		||||
inline bool operator<=(const Rule& x, const Rule& y) {return !(y < x);}
 | 
			
		||||
inline bool operator>=(const Rule& x, const Rule& y) {return !(x < y);}
 | 
			
		||||
 | 
			
		||||
inline bool operator!=(const Rule& x, const date::year& y) {return !(x == y);}
 | 
			
		||||
inline bool operator> (const Rule& x, const date::year& y) {return   y < x;}
 | 
			
		||||
inline bool operator<=(const Rule& x, const date::year& y) {return !(y < x);}
 | 
			
		||||
inline bool operator>=(const Rule& x, const date::year& y) {return !(x < y);}
 | 
			
		||||
 | 
			
		||||
inline bool operator!=(const date::year& x, const Rule& y) {return !(x == y);}
 | 
			
		||||
inline bool operator> (const date::year& x, const Rule& y) {return   y < x;}
 | 
			
		||||
inline bool operator<=(const date::year& x, const Rule& y) {return !(y < x);}
 | 
			
		||||
inline bool operator>=(const date::year& x, const Rule& y) {return !(x < y);}
 | 
			
		||||
 | 
			
		||||
inline bool operator!=(const Rule& x, const std::string& y) {return !(x == y);}
 | 
			
		||||
inline bool operator> (const Rule& x, const std::string& y) {return   y < x;}
 | 
			
		||||
inline bool operator<=(const Rule& x, const std::string& y) {return !(y < x);}
 | 
			
		||||
inline bool operator>=(const Rule& x, const std::string& y) {return !(x < y);}
 | 
			
		||||
 | 
			
		||||
inline bool operator!=(const std::string& x, const Rule& y) {return !(x == y);}
 | 
			
		||||
inline bool operator> (const std::string& x, const Rule& y) {return   y < x;}
 | 
			
		||||
inline bool operator<=(const std::string& x, const Rule& y) {return !(y < x);}
 | 
			
		||||
inline bool operator>=(const std::string& x, const Rule& y) {return !(x < y);}
 | 
			
		||||
 | 
			
		||||
struct zonelet
 | 
			
		||||
{
 | 
			
		||||
    enum tag {has_rule, has_save, is_empty};
 | 
			
		||||
 | 
			
		||||
    std::chrono::seconds gmtoff_;
 | 
			
		||||
    tag tag_ = has_rule;
 | 
			
		||||
 | 
			
		||||
#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
 | 
			
		||||
    union U
 | 
			
		||||
#else
 | 
			
		||||
    struct U
 | 
			
		||||
#endif
 | 
			
		||||
    {
 | 
			
		||||
        std::string          rule_;
 | 
			
		||||
        std::chrono::minutes save_;
 | 
			
		||||
 | 
			
		||||
        ~U() {}
 | 
			
		||||
        U() {}
 | 
			
		||||
        U(const U&) {}
 | 
			
		||||
        U& operator=(const U&) = delete;
 | 
			
		||||
    } u;
 | 
			
		||||
 | 
			
		||||
    std::string                        format_;
 | 
			
		||||
    date::year                         until_year_{0};
 | 
			
		||||
    MonthDayTime                       until_date_;
 | 
			
		||||
    sys_seconds                        until_utc_;
 | 
			
		||||
    local_seconds                      until_std_;
 | 
			
		||||
    local_seconds                      until_loc_;
 | 
			
		||||
    std::chrono::minutes               initial_save_{};
 | 
			
		||||
    std::string                        initial_abbrev_;
 | 
			
		||||
    std::pair<const Rule*, date::year> first_rule_{nullptr, date::year::min()};
 | 
			
		||||
    std::pair<const Rule*, date::year> last_rule_{nullptr, date::year::max()};
 | 
			
		||||
 | 
			
		||||
    ~zonelet();
 | 
			
		||||
    zonelet();
 | 
			
		||||
    zonelet(const zonelet& i);
 | 
			
		||||
    zonelet& operator=(const zonelet&) = delete;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#else  // USE_OS_TZDB
 | 
			
		||||
 | 
			
		||||
struct ttinfo
 | 
			
		||||
{
 | 
			
		||||
    std::int32_t  tt_gmtoff;
 | 
			
		||||
    unsigned char tt_isdst;
 | 
			
		||||
    unsigned char tt_abbrind;
 | 
			
		||||
    unsigned char pad[2];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static_assert(sizeof(ttinfo) == 8, "");
 | 
			
		||||
 | 
			
		||||
struct expanded_ttinfo
 | 
			
		||||
{
 | 
			
		||||
    std::chrono::seconds offset;
 | 
			
		||||
    std::string          abbrev;
 | 
			
		||||
    bool                 is_dst;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct transition
 | 
			
		||||
{
 | 
			
		||||
    sys_seconds            timepoint;
 | 
			
		||||
    const expanded_ttinfo* info;
 | 
			
		||||
 | 
			
		||||
    transition(sys_seconds tp, const expanded_ttinfo* i = nullptr)
 | 
			
		||||
        : timepoint(tp)
 | 
			
		||||
        , info(i)
 | 
			
		||||
        {}
 | 
			
		||||
 | 
			
		||||
    friend
 | 
			
		||||
    std::ostream&
 | 
			
		||||
    operator<<(std::ostream& os, const transition& t)
 | 
			
		||||
    {
 | 
			
		||||
        using date::operator<<;
 | 
			
		||||
        os << t.timepoint << "Z ";
 | 
			
		||||
        if (t.info->offset >= std::chrono::seconds{0})
 | 
			
		||||
            os << '+';
 | 
			
		||||
        os << make_time(t.info->offset);
 | 
			
		||||
        if (t.info->is_dst > 0)
 | 
			
		||||
            os << " daylight ";
 | 
			
		||||
        else
 | 
			
		||||
            os << " standard ";
 | 
			
		||||
        os << t.info->abbrev;
 | 
			
		||||
        return os;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif  // USE_OS_TZDB
 | 
			
		||||
 | 
			
		||||
}  // namespace detail
 | 
			
		||||
 | 
			
		||||
}  // namespace date
 | 
			
		||||
 | 
			
		||||
#if defined(_MSC_VER) && (_MSC_VER < 1900)
 | 
			
		||||
#include "tz.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif  // TZ_PRIVATE_H
 | 
			
		||||
							
								
								
									
										3825
									
								
								src/libs/date/src/tz.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3825
									
								
								src/libs/date/src/tz.cpp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user