Time Shield Library
C++ library for working with time
Loading...
Searching...
No Matches
ZonedClock.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: MIT
2#pragma once
3#ifndef _TIME_SHIELD_ZONED_CLOCK_HPP_INCLUDED
4#define _TIME_SHIELD_ZONED_CLOCK_HPP_INCLUDED
5
8
9#include "config.hpp"
10#include "constants.hpp"
11#include "DateTime.hpp"
12#include "enums.hpp"
13#include "time_parser.hpp"
14#include "time_utils.hpp"
17
18#if TIME_SHIELD_ENABLE_NTP_CLIENT
19# include "ntp_time_service.hpp"
20#endif
21
22#include <cstddef>
23#include <stdexcept>
24#include <string>
25
26namespace time_shield {
27
33 class ZonedClock final {
34 public:
36 ZonedClock() noexcept
38 , m_offset(0)
39 , m_is_named_zone(false)
40 , m_use_ntp(false) {}
41
45 explicit ZonedClock(TimeZone zone, bool use_ntp = false) noexcept
47 , m_offset(0)
48 , m_is_named_zone(false)
51 }
52
57 explicit ZonedClock(tz_t utc_offset, bool use_ntp = false)
59 , m_offset(0)
60 , m_is_named_zone(false)
62 if (!try_set_offset(utc_offset)) {
63 throw std::invalid_argument("Invalid UTC offset");
64 }
65 }
66
71 static bool try_from_offset(tz_t utc_offset, ZonedClock& out) noexcept {
72 ZonedClock candidate;
73 if (!candidate.try_set_offset(utc_offset)) {
74 return false;
75 }
76 out = candidate;
77 return true;
78 }
79
82 void set_zone(TimeZone zone) noexcept {
83 if (zone == UNKNOWN) {
85 m_offset = 0;
86 m_is_named_zone = false;
87 return;
88 }
89
90 m_zone = zone;
91 m_offset = 0;
92 m_is_named_zone = true;
93 }
94
98 bool try_set_offset(tz_t utc_offset) noexcept {
99 if (!is_valid_tz_offset(utc_offset)) {
100 return false;
101 }
102
103 m_zone = UNKNOWN;
104 m_offset = utc_offset;
105 m_is_named_zone = false;
106 return true;
107 }
108
112 bool try_set_zone(const std::string& zone_spec) noexcept {
113 const std::string trimmed = trim_ascii(zone_spec);
114 if (trimmed.empty()) {
115 return false;
116 }
117
118 TimeZone parsed_zone = UNKNOWN;
119 if (parse_time_zone_name(trimmed, parsed_zone)) {
120 set_zone(parsed_zone);
121 return true;
122 }
123
124 TimeZoneStruct parsed_offset = create_time_zone_struct(0, 0, true);
125 if (!parse_time_zone(trimmed, parsed_offset)) {
126 return false;
127 }
128
129 return try_set_offset(time_zone_struct_to_offset(parsed_offset));
130 }
131
134 void set_use_ntp(bool use_ntp) noexcept {
136 }
137
139 bool has_named_zone() const noexcept {
140 return m_is_named_zone;
141 }
142
144 TimeZone zone() const noexcept {
145 return m_is_named_zone ? m_zone : UNKNOWN;
146 }
147
149 bool use_ntp() const noexcept {
150 return m_use_ntp;
151 }
152
154 bool ntp_active() const noexcept {
155#if TIME_SHIELD_ENABLE_NTP_CLIENT
157#else
158 return false;
159#endif
160 }
161
163 tz_t offset_now() const noexcept {
165 }
166
170 tz_t offset_at_utc_ms(ts_ms_t utc_ms) const noexcept {
171 if (!m_is_named_zone) {
172 return m_offset;
173 }
174
175 const ts_ms_t local_ms = gmt_to_zone_ms(utc_ms, m_zone);
176 if (local_ms == ERROR_TIMESTAMP) {
177 return 0;
178 }
179
180 const ts_ms_t delta_ms = local_ms - utc_ms;
181 return static_cast<tz_t>(delta_ms / MS_PER_SEC);
182 }
183
185 ts_t utc_time_sec() const noexcept {
186 return static_cast<ts_t>(current_utc_us() / US_PER_SEC);
187 }
188
190 ts_ms_t utc_time_ms() const noexcept {
191 return current_utc_ms();
192 }
193
195 ts_us_t utc_time_us() const noexcept {
196 return current_utc_us();
197 }
198
200 ts_t local_time_sec() const noexcept {
201 const ts_t utc_sec = utc_time_sec();
202 return utc_sec + static_cast<ts_t>(offset_at_utc_ms(static_cast<ts_ms_t>(utc_sec) * MS_PER_SEC));
203 }
204
206 ts_ms_t local_time_ms() const noexcept {
207 const ts_ms_t utc_ms = current_utc_ms();
208 return utc_ms + static_cast<ts_ms_t>(offset_at_utc_ms(utc_ms)) * MS_PER_SEC;
209 }
210
212 ts_us_t local_time_us() const noexcept {
213 const ts_us_t utc_us = current_utc_us();
214 return utc_us + static_cast<ts_us_t>(offset_at_utc_ms(static_cast<ts_ms_t>(utc_us / MS_PER_SEC))) * US_PER_SEC;
215 }
216
218 DateTime now() const noexcept {
219 return from_utc_ms(current_utc_ms());
220 }
221
225 DateTime from_utc_ms(ts_ms_t utc_ms) const noexcept {
226 return DateTime::from_unix_ms(utc_ms, offset_at_utc_ms(utc_ms));
227 }
228
232 DateTime from_utc_s(ts_t utc_s) const noexcept {
233 return from_utc_ms(static_cast<ts_ms_t>(utc_s) * MS_PER_SEC);
234 }
235
238 std::string zone_name() const {
239 return m_is_named_zone ? std::string(to_cstr(m_zone)) : std::string();
240 }
241
244 std::string zone_full_name() const {
245 if (m_is_named_zone) {
246 return to_str(m_zone, FULL_NAME);
247 }
248 return std::string("UTC") + offset_string_for_offset(m_offset);
249 }
250
252 std::string offset_string() const {
254 }
255
257 std::string to_iso8601() const {
258 return now().to_iso8601();
259 }
260
262 std::string to_iso8601_utc() const {
263 return now().to_iso8601_utc();
264 }
265
269 std::string format(const std::string& fmt) const {
270 return now().format(fmt);
271 }
272
273 private:
274 static std::string trim_ascii(const std::string& value) {
275 std::size_t begin = 0;
276 std::size_t end = value.size();
277 while (begin < end && is_ascii_space(value[begin])) {
278 ++begin;
279 }
280 while (end > begin && is_ascii_space(value[end - 1])) {
281 --end;
282 }
283 return value.substr(begin, end - begin);
284 }
285
286 static bool is_ascii_space(char ch) noexcept {
287 return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' || ch == '\f' || ch == '\v';
288 }
289
290 static std::string offset_string_for_offset(tz_t utc_offset) {
292 }
293
294 ts_ms_t current_utc_ms() const noexcept {
295 return static_cast<ts_ms_t>(current_utc_us() / 1000);
296 }
297
298 ts_us_t current_utc_us() const noexcept {
299#if TIME_SHIELD_ENABLE_NTP_CLIENT
300 if (m_use_ntp) {
301 if (!NtpTimeService::instance().running()) {
302 (void)ntp::init(30000, true);
303 }
304 return static_cast<ts_us_t>(ntp::utc_time_us());
305 }
306#endif
307 return static_cast<ts_us_t>(now_realtime_us());
308 }
309
310 private:
315 };
316
317} // namespace time_shield
318
319#endif // _TIME_SHIELD_ZONED_CLOCK_HPP_INCLUDED
Value-type wrapper for timestamps with fixed UTC offset.
Represents a moment in time with optional fixed UTC offset.
Definition DateTime.hpp:37
std::string to_iso8601() const
Format to ISO8601 string with stored offset.
Definition DateTime.hpp:248
std::string format(const std::string &fmt) const
Format using custom pattern.
Definition DateTime.hpp:258
static DateTime from_unix_ms(ts_ms_t utc_ms, tz_t offset=0) noexcept
Create instance from UTC milliseconds.
Definition DateTime.hpp:48
std::string to_iso8601_utc() const
Format to ISO8601 string in UTC.
Definition DateTime.hpp:253
bool running() const noexcept
Return true when background runner is active.
tz_t offset_at_utc_ms(ts_ms_t utc_ms) const noexcept
Return effective UTC offset in seconds for a specific UTC instant.
static bool is_ascii_space(char ch) noexcept
std::string zone_full_name() const
Return human-readable zone label.
ts_us_t local_time_us() const noexcept
Return current local timestamp in microseconds.
std::string to_iso8601() const
Return current local time formatted as ISO8601 with offset.
DateTime from_utc_s(ts_t utc_s) const noexcept
Return a snapshot for a specific UTC instant in seconds.
ts_t local_time_sec() const noexcept
Return current local timestamp in seconds.
bool ntp_active() const noexcept
Return true when the global NTP service is active for this clock.
static std::string trim_ascii(const std::string &value)
bool try_set_offset(tz_t utc_offset) noexcept
Set the stored fixed UTC offset.
ts_ms_t current_utc_ms() const noexcept
DateTime now() const noexcept
Return current time snapshot with resolved fixed offset.
bool use_ntp() const noexcept
Return the preferred UTC source flag.
bool try_set_zone(const std::string &zone_spec) noexcept
Parse and set a named zone or numeric offset from string.
std::string to_iso8601_utc() const
Return current UTC time formatted as ISO8601 with Z.
static bool try_from_offset(tz_t utc_offset, ZonedClock &out) noexcept
Try to build fixed-offset clock without throwing.
DateTime from_utc_ms(ts_ms_t utc_ms) const noexcept
Return a snapshot for a specific UTC instant in milliseconds.
std::string zone_name() const
Return short name of the stored named zone.
tz_t offset_now() const noexcept
Return effective UTC offset in seconds for the current UTC instant.
std::string format(const std::string &fmt) const
Format current local time using the custom formatter grammar.
std::string offset_string() const
Return effective numeric UTC offset as +HH:MM or -HH:MM.
ZonedClock(TimeZone zone, bool use_ntp=false) noexcept
Construct clock for a named zone.
static std::string offset_string_for_offset(tz_t utc_offset)
ZonedClock(tz_t utc_offset, bool use_ntp=false)
Construct clock for a fixed UTC offset.
ts_ms_t local_time_ms() const noexcept
Return current local timestamp in milliseconds.
void set_use_ntp(bool use_ntp) noexcept
Set preferred UTC source.
ts_ms_t utc_time_ms() const noexcept
Return current UTC time in milliseconds.
ts_t utc_time_sec() const noexcept
Return current UTC time in seconds.
void set_zone(TimeZone zone) noexcept
Set the stored named zone.
TimeZone zone() const noexcept
Return stored named zone or UNKNOWN for fixed-offset mode.
bool has_named_zone() const noexcept
Return true when the instance stores a named zone.
ZonedClock() noexcept
Construct UTC fixed-offset clock without NTP.
ts_us_t utc_time_us() const noexcept
Return current UTC time in microseconds.
ts_us_t current_utc_us() const noexcept
Configuration macros for the library.
Header file with time-related constants.
Header file with enumerations for weekdays, months, and other time-related categories.
@ FULL_NAME
Full name.
Definition enums.hpp:22
bool init(std::chrono::milliseconds interval=std::chrono::seconds(30), bool measure_immediately=true)
Initialize NTP time service and start background measurements.
int64_t utc_time_us() noexcept
Return current UTC time in microseconds based on offset.
constexpr int64_t ERROR_TIMESTAMP
Error timestamp value.
constexpr int64_t MS_PER_SEC
Milliseconds per second.
Definition constants.hpp:77
constexpr int64_t US_PER_SEC
Microseconds per second.
Definition constants.hpp:76
ts_ms_t gmt_to_zone_ms(ts_ms_t gmt_ms, TimeZone zone)
Convert GMT (UTC) in milliseconds to a supported local civil time zone.
TIME_SHIELD_CONSTEXPR bool is_valid_tz_offset(tz_t off) noexcept
Check if a numeric offset is within supported bounds.
const std::string & to_str(Weekday value, FormatType format=UPPERCASE_NAME)
Converts a Weekday enum value to a string.
Definition enums.hpp:70
const char * to_cstr(Weekday value, FormatType format=UPPERCASE_NAME)
Converts a Weekday enum value to a string.
Definition enums.hpp:43
@ UNKNOWN
Unknown Time Zone.
Definition enums.hpp:202
bool parse_time_zone_name(const char *data, std::size_t length, TimeZone &zone) noexcept
Parse named time zone character buffer into TimeZone enum.
bool parse_time_zone(const char *data, std::size_t length, TimeZoneStruct &tz) noexcept
Parse timezone character buffer into TimeZoneStruct.
TIME_SHIELD_CONSTEXPR tz_t time_zone_struct_to_offset(const TimeZoneStruct &tz) noexcept
Convert a TimeZoneStruct to a numeric UTC offset (seconds).
TimeZoneStruct to_time_zone_struct(tz_t offset)
Converts an integer to a TimeZoneStruct.
std::string time_zone_struct_to_string(const TimeZoneStruct &tz)
Converts a TimeZoneStruct to a string representation.
TimeZoneStruct create_time_zone_struct(int hour, int min, bool is_positive=true)
Creates a TimeZoneStruct instance.
int64_t ts_t
Unix timestamp in seconds since 1970‑01‑01T00:00:00Z.
Definition types.hpp:49
int32_t tz_t
Time zone offset in minutes from UTC (e.g., +180 = UTC+3).
Definition types.hpp:61
int64_t ts_ms_t
Unix timestamp in milliseconds since epoch.
Definition types.hpp:50
int64_t ts_us_t
Unix timestamp in microseconds since epoch.
Definition types.hpp:51
int64_t now_realtime_us()
Get current real time in microseconds using a platform-specific method.
Main namespace for the Time Shield library.
Structure to represent time zone information.
Header file with functions for parsing dates and times in ISO8601 format and converting them to vario...
Header file with time-related utility functions.
Helpers for converting supported regional time zones and UTC.
Conversions between numeric offsets and TimeZoneStruct.