Toolbox snapshot
The Reactive C++ Toolbox
Loading...
Searching...
No Matches
Date.hpp
Go to the documentation of this file.
1// The Reactive C++ Toolbox.
2// Copyright (C) 2013-2019 Swirly Cloud Limited
3// Copyright (C) 2022 Reactive Markets Limited
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17#ifndef TOOLBOX_SYS_DATE_HPP
18#define TOOLBOX_SYS_DATE_HPP
19
20#include <toolbox/sys/Time.hpp>
22
23namespace toolbox {
24inline namespace sys {
25
28
31
32constexpr auto operator""_ymd(unsigned long long val) noexcept
33{
34 return IsoDate{val};
35}
36
39
40constexpr auto operator""_jd(unsigned long long val) noexcept
41{
42 return JDay{val};
43}
44
46constexpr auto ymd_to_iso(int year, int mon, int mday) noexcept
47{
48 assert(mon > 0 && mon <= 12);
49 assert(mday > 0 && mday <= 31);
50 return IsoDate{year * 10000 + mon * 100 + mday};
51}
52
54constexpr auto ymd_to_jd(int year, int mon, int mday) noexcept
55{
56 // The formula given below was taken from the 1990 edition of the U.S. Naval Observatory's Almanac
57 // for Computers.
58 // See http://aa.usno.navy.mil/faq/docs/JD_Formula.php.
59
60 const auto i = year;
61 const auto j = mon;
62 const auto k = mday;
63 return JDay{k - 32075 + 1461 * (i + 4800 + (j - 14) / 12) / 4
64 + 367 * (j - 2 - (j - 14) / 12 * 12) / 12
65 - 3 * ((i + 4900 + (j - 14) / 12) / 100) / 4};
66}
67
69constexpr auto iso_to_jd(IsoDate iso) noexcept
70{
71 const auto n = iso.count();
72 const auto year = n / 10000;
73 const auto mon = (n / 100 % 100);
74 const auto mday = n % 100;
75 return ymd_to_jd(year, mon, mday);
76}
77
79constexpr auto jd_to_iso(JDay jd) noexcept
80{
81 // The formula given above was taken from the 1990 edition of the U.S. Naval Observatory's
82 // Almanac for Computers.
83 // See http://aa.usno.navy.mil/faq/docs/JD_Formula.php.
84
85 auto l = jd.count() + 68569;
86 const auto n = 4 * l / 146097;
87 l = l - (146097 * n + 3) / 4;
88 auto i = 4000 * (l + 1) / 1461001;
89 l = l - 1461 * i / 4 + 31;
90 auto j = 80 * l / 2447;
91 const auto k = l - 2447 * j / 80;
92 l = j / 11;
93 j = j + 2 - 12 * l;
94 i = 100 * (n - 49) + i + l;
95
96 return IsoDate{i * 10000 + j * 100 + k};
97}
98
100constexpr std::int32_t jd_to_mjd(JDay jd) noexcept
101{
102 return jd.count() - 2400000;
103}
104
106constexpr auto mjd_to_jd(std::int32_t mjd) noexcept
107{
108 return JDay{mjd + 2400000};
109}
110
112constexpr std::int32_t jd_to_tjd(JDay jd) noexcept
113{
114 return jd.count() - 2440000;
115}
116
118constexpr JDay tjd_to_jd(std::int32_t tjd) noexcept
119{
120 return JDay{tjd + 2440000};
121}
122
124constexpr WallTime jd_to_time(JDay jd) noexcept
125{
126 // Julian day for January 1st, 1970.
127 const JDay jd_unix_epoc = 2440588_jd;
128 const std::int64_t ms_in_day = 24 * 60 * 60 * 1000;
129 // Add half day for 12pm.
130 return to_time<WallClock>(Millis{(jd - jd_unix_epoc).count() * ms_in_day + (ms_in_day >> 1)});
131}
132
134constexpr IsoDate maybe_jd_to_iso(JDay jd) noexcept
135{
136 return jd != 0_jd ? jd_to_iso(jd) : 0_ymd;
137}
138
140constexpr JDay maybe_iso_to_jd(IsoDate iso) noexcept
141{
142 return iso != 0_ymd ? iso_to_jd(iso) : 0_jd;
143}
144
145constexpr bool is_week_day(JDay jday) noexcept
146{
147 return (jday.count() % 7) < 5;
148}
149
150constexpr bool is_weekend_day(JDay jday) noexcept
151{
152 return !is_week_day(jday);
153}
154
163constexpr auto parse_date(std::string_view sv) noexcept
164{
166}
167static_assert(parse_date("20180117") == 20180117_ymd);
168
181constexpr std::optional<WallTime> parse_time(std::string_view sv) noexcept
182{
183 if (sv.size() < 8) {
184 // Date part is too short.
185 return {};
186 }
187 const IsoDate d{parse_date(sv.substr(0, 8))};
188 WallTime dt{};
189 if (d != 0_ymd) {
190 // Julian days start at noon.
191 dt = jd_to_time(iso_to_jd(d)) - 12h;
192 }
193 // If there is a time component.
194 if (sv.size() > 8) {
195 if (sv[8] != '-' && sv[8] != 'T') {
196 // Invalid delimiter.
197 return {};
198 }
199 const auto t = parse_time_only(sv.substr(9));
200 if (!t) {
201 // Invalid time.
202 return {};
203 }
204 dt += *t;
205 }
206 return dt;
207}
208static_assert(ms_since_epoch(*parse_time("20180824-05:32:29.123"sv)) == 1535088749123);
209
210} // namespace sys
211} // namespace toolbox
212
213#endif // TOOLBOX_SYS_DATE_HPP
constexpr bool is_weekend_day(JDay jday) noexcept
Definition Date.hpp:150
constexpr std::int32_t jd_to_tjd(JDay jd) noexcept
Julian day to Truncated Julian day. Epoch is May 24, 1968.
Definition Date.hpp:112
constexpr WallTime jd_to_time(JDay jd) noexcept
Julian day to Unix time.
Definition Date.hpp:124
constexpr std::optional< Nanos > parse_time_only(std::string_view sv) noexcept
Definition Time.hpp:399
constexpr std::int64_t ms_since_epoch(std::chrono::time_point< ClockT, Duration > t) noexcept
Definition Time.hpp:176
constexpr JDay tjd_to_jd(std::int32_t tjd) noexcept
Truncated Julian day to Julian day. Epoch is May 24, 1968.
Definition Date.hpp:118
constexpr IsoDate maybe_jd_to_iso(JDay jd) noexcept
Julian day to ISO8601 if argument is non-zero.
Definition Date.hpp:134
constexpr std::int32_t jd_to_mjd(JDay jd) noexcept
Juilian day to Modified Julian day. Epoch is November 17, 1858.
Definition Date.hpp:100
std::chrono::milliseconds Millis
Definition Time.hpp:35
WallClock::time_point WallTime
Definition Time.hpp:111
constexpr auto jd_to_iso(JDay jd) noexcept
Julian day to ISO8601.
Definition Date.hpp:79
constexpr auto ymd_to_iso(int year, int mon, int mday) noexcept
Gregorian to ISO8601 date.
Definition Date.hpp:46
constexpr auto mjd_to_jd(std::int32_t mjd) noexcept
Modified Julian day to Julian day. Epoch is November 17, 1858.
Definition Date.hpp:106
constexpr auto iso_to_jd(IsoDate iso) noexcept
ISO8601 to Julian day.
Definition Date.hpp:69
constexpr std::optional< WallTime > parse_time(std::string_view sv) noexcept
Definition Date.hpp:181
constexpr JDay maybe_iso_to_jd(IsoDate iso) noexcept
ISO8601 to Julian day if argument is non-zero.
Definition Date.hpp:140
constexpr auto ymd_to_jd(int year, int mon, int mday) noexcept
Gregorian date to Julian day.
Definition Date.hpp:54
constexpr auto parse_date(std::string_view sv) noexcept
Definition Date.hpp:163
constexpr bool is_week_day(JDay jday) noexcept
Definition Date.hpp:145
std::string_view sv
Definition Tokeniser.hpp:26
constexpr auto bind() noexcept
Definition Slot.hpp:92
constexpr ValueType count() const noexcept
Definition IntTypes.hpp:59