ALib C++ Library
Library Version: 2510 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
calendar.cpp
1// #################################################################################################
2// ALib C++ Library
3//
4// Copyright 2013-2025 A-Worx GmbH, Germany
5// Published under 'Boost Software License' (a free software license, see LICENSE.txt)
6// #################################################################################################
7#include "alib_precompile.hpp"
8#if !defined(ALIB_C20_MODULES) || ((ALIB_C20_MODULES != 0) && (ALIB_C20_MODULES != 1))
9# error "Symbol ALIB_C20_MODULES has to be given to the compiler as either 0 or 1"
10#endif
11#if ALIB_C20_MODULES
12 module;
13#endif
14// ====================================== Global Fragment ======================================
16// =========================================== Module ==========================================
17#if ALIB_C20_MODULES
19 import ALib.Lang;
20#else
21# include "ALib.Lang.H"
22# include "ALib.Strings.H"
24#endif
25// ====================================== Implementation =======================================
26
27namespace alib::strings::util {
28
29#if !DOXYGEN
31#if ALIB_CAMP
32 ;
33#else
34DOX_MARKER( [CDT_MONTH_NAMES])
35={ A_CHAR("January" ), A_CHAR("February" ),
36 A_CHAR("March" ), A_CHAR("April" ),
37 A_CHAR("May" ), A_CHAR("June" ),
38 A_CHAR("July" ), A_CHAR("August" ),
39 A_CHAR("September"), A_CHAR("October" ),
40 A_CHAR("November" ), A_CHAR("December" ) };
41DOX_MARKER( [CDT_MONTH_NAMES])
42
43#endif
44
46#if ALIB_CAMP
47 ;
48#else
49DOX_MARKER( [CDT_DAY_NAMES])
50={ A_CHAR("Sunday" ), A_CHAR("Monday" ),
51 A_CHAR("Tuesday" ), A_CHAR("Wednesday"),
52 A_CHAR("Thursday" ), A_CHAR("Friday" ),
53 A_CHAR("Saturday" ) };
54DOX_MARKER( [CDT_DAY_NAMES])
55#endif
56
57#endif // !DOXYGEN
58
59
60// #################################################################################################
61// CalendarDateTime
62// #################################################################################################
64{
65 Year=
66 Month=
67 Day=
68 Hour=
69 Minute=
70 Second=
71 Millisecond= 0;
72 DayOfWeek= -1;
73}
74
75void CalendarDateTime::Set( const DateTime& timeStamp, lang::Timezone timezone )
76{
77 Clear();
78
79 #if defined( _WIN32 )
80 SYSTEMTIME st= timeStamp.ToSystemTime( timezone );
81
82 Year= st.wYear;
83 Day= st.wDay;
84 DayOfWeek= st.wDayOfWeek;
85 Month= st.wMonth;
86 Hour= st.wHour;
87 Minute= st.wMinute;
88 Second= st.wSecond;
89
90 #elif defined (__GLIBCXX__) || defined(_LIBCPP_VERSION) || defined(__APPLE__) || defined(__ANDROID_NDK__)
91 struct tm tm;
92 time_t tt= timeStamp.InEpochSeconds();
93 if ( timezone == lang::Timezone::UTC )
94 {
95 tm.tm_isdst= 0; // daylight saving off
96 gmtime_r( &tt, &tm );
97 }
98 else
99 {
100 tm.tm_isdst= -1; // daylight saving auto
101 localtime_r( &tt, &tm );
102 }
103
104 Year= tm.tm_year + 1900;
105 Day= tm.tm_mday;
106 DayOfWeek= tm.tm_wday;
107 Month= tm.tm_mon + 1;
108 Second= tm.tm_sec;
109 Hour= tm.tm_hour;
110 Minute= tm.tm_min;
111
112 #else
113 #pragma message ("Unknown Platform in file: " __FILE__ )
114 #endif
115}
116
118{
120
121 #if defined( _WIN32 )
122
123 SYSTEMTIME st;
124 st.wYear= (WORD) Year;
125 st.wDay= (WORD) Day;
126 st.wDayOfWeek= (WORD) DayOfWeek;
127 st.wMonth= (WORD) Month;
128 st.wHour= (WORD) Hour;
129 st.wMinute= (WORD) Minute;
130 st.wSecond= (WORD) Second;
131 st.wMilliseconds= 0;
132
133 result= DateTime::FromSystemTime( st, timezone );
134
135 #elif defined (__GLIBCXX__) || defined(_LIBCPP_VERSION) || defined(__APPLE__) || defined(__ANDROID_NDK__)
136 struct tm tm;
137 tm.tm_year= Year - 1900;
138 tm.tm_mday= Day;
139 tm.tm_mon= Month -1;
140 tm.tm_hour= Hour;
141 tm.tm_min= Minute;
142 tm.tm_sec= Second;
143
144 time_t tt;
145 if ( timezone == lang::Timezone::UTC )
146 {
147 tm.tm_isdst= 0; // daylight saving off
148 tt= timegm( &tm );
149 }
150 else
151 {
152 tm.tm_isdst= -1; // daylight saving auto
153 tt= mktime( &tm );
154 }
155
156 result= DateTime::FromEpochSeconds( tt );
157
158
159 #else
160 #pragma message ("Unknown Platform in file: " __FILE__ )
161 #endif
162
163 return result;
164}
165
166
167
168// #################################################################################################
169// CalendarDuration
170// #################################################################################################
172{
173 Days=
174 Hours=
175 Minutes=
176 Seconds=
179 Nanoseconds= 0;
180}
181#define NanosPerDay INT64_C( 86400000000000 ) ///< Constant denoting number of nanoseconds of a day.
182#define NanosPerHour INT64_C( 3600000000000 ) ///< Constant denoting number of nanoseconds of an hour.
183#define NanosPerMinute INT64_C( 60000000000 ) ///< Constant denoting number of nanoseconds of a minute.
184#define NanosPerSecond INT64_C( 1000000000 ) ///< Constant denoting number of nanoseconds of a second.
185#define NanosPerMillisecond INT64_C( 1000000 ) ///< Constant denoting number of nanoseconds of a millisecond.
186#define NanosPerMicrosecond INT64_C( 1000 ) ///< Constant denoting number of nanoseconds of a microsecond.
187
188
190{
191 Clear();
192 decltype(nanos) fract;
193 if ( nanos > NanosPerDay ) { Days= int( fract= nanos / NanosPerDay ); nanos-= fract * NanosPerDay; }
194 if ( nanos > NanosPerHour ) { Hours= int( fract= nanos / NanosPerHour ); nanos-= fract * NanosPerHour; }
195 if ( nanos > NanosPerMinute ) { Minutes= int( fract= nanos / NanosPerMinute ); nanos-= fract * NanosPerMinute; }
196 if ( nanos > NanosPerSecond ) { Seconds= int( fract= nanos / NanosPerSecond ); nanos-= fract * NanosPerSecond; }
197 if ( nanos > NanosPerMillisecond ) { Milliseconds= int( fract= nanos / NanosPerMillisecond ); nanos-= fract * NanosPerMillisecond; }
198 if ( nanos > NanosPerMicrosecond ) { Microseconds= int( fract= nanos / NanosPerMicrosecond ); }
199}
200
202{
203 return Days * NanosPerDay
204 + Hours * NanosPerHour
205 + Minutes * NanosPerMinute
206 + Seconds * NanosPerSecond
207 + Milliseconds * NanosPerMillisecond
208 + Microseconds * NanosPerMicrosecond
209 + Nanoseconds;
210}
211
212// #################################################################################################
213// CalendarDate
214// #################################################################################################
215void CalendarDate::Set( const DateTime& dateTime, lang::Timezone timezone )
216{
217 CalendarDateTime cdt(dateTime, timezone);
218 stamp= uint32_t( cdt.Year ) << 12
219 | uint32_t( cdt.Month ) << 8
220 | uint32_t( cdt.Day ) << 3
221 | uint32_t( cdt.DayOfWeek ) ;
222}
223void CalendarDate::Set( int year, int month, int day, int dayOfWeek )
224{
225 ALIB_ASSERT_ERROR( year >= 0 && year <= 1048575, "CAMP", "CalendarDate: Years must be between 0 and 1,048,575. Given: ", year )
226 ALIB_ASSERT_ERROR( month >= 1 && month <= 12 , "CAMP", "CalendarDate: Months must be between 1 and 12. Given: ", month )
227 ALIB_ASSERT_ERROR( day >= 1 && day <= 31 , "CAMP", "CalendarDate: Days must be between 1 and 31. Given: ", day )
228 ALIB_ASSERT_ERROR( dayOfWeek <= 6 , "CAMP", "CalendarDate: Day of week must be either negative or between 0 and 6. Given: ", dayOfWeek)
229
230 // get day of week, if not given
231 if( dayOfWeek< 0 )
232 {
233 dayOfWeek= CalendarDateTime( CalendarDateTime( year, month, day, 12, 0, 0 ).Get(),
235 }
236 #if ALIB_DEBUG
237 else
238 {
239 CalendarDateTime cdt( year, month, day, 12, 0, 0 );
240 cdt= CalendarDateTime( cdt.Get( )); // get day of week
241 ALIB_ASSERT_ERROR( dayOfWeek == cdt.DayOfWeek, "CAMP",
242 "Given day of week {} does not correspond to given date. Should be: ",
243 dayOfWeek, cdt.DayOfWeek )
244 }
245 #endif
246 stamp= uint32_t( year ) << 12
247 | uint32_t( month ) << 8
248 | uint32_t( day ) << 3
249 | uint32_t( dayOfWeek ) ;
250}
251
252DateTime CalendarDate::Get( lang::Timezone timezone, int hour, int minute, int second ) const
253{
254 return CalendarDateTime( Year(), Month(), Day(), hour, minute, second).Get( timezone );
255}
256
258{
259 // use the system for it
260 return CalendarDate( CalendarDateTime( Year(), Month(), Day(), 12 ).Get()
261 + DateTime::Duration::FromAbsoluteDays( daysToAdd ),
263}
264
266{
267 auto day = Day ();
268 auto month= Month();
269 auto year = Year ();
270
271 // can we do it manually?
272 if( ( month != 2 && day != 30 )
273 || ( month == 2 && day != 28 ) )
274 {
275 if( ( day != 31 )
276 && ( day != 29 || month != 2 ) )
277 {
278 day++;
279 }
280 else
281 {
282 day= 1;
283 if( ++month == 13 )
284 {
285 month= 1;
286 ++year;
287 }
288 }
289 Set( year, month, day, (DayOfWeek() + 1) % 7 );
290 return *this;
291 }
292
293 // use the system for it
294 CalendarDateTime cdt( year, month, day, 12 );
295 return *this= CalendarDate( cdt.Get() + DateTime::Duration::FromAbsoluteDays(1), lang::Timezone::UTC );
296}
297
299{
300 auto day = Day();
301
302 // can we do it manually?
303 if( day > 1 )
304 {
305 stamp= ( stamp & ~lang::LowerMask<8, uint32_t>() )
306 | ( uint32_t( day-1 ) << 3 )
307 | ( ( (stamp & 7) + 6 ) % 7 ) ; // +6 corresponds to -1 in modulo op
308 return *this;
309 }
310
311 // use the system for it
312 return *this= CalendarDate( Get() - DateTime::Duration::FromAbsoluteDays(1), lang::Timezone::UTC );
313}
314
315
316// #################################################################################################
317// CalendarDateTime::Format
318// #################################################################################################
320{
321 if ( targetData == lang::CurrentData::Clear )
322 target.Reset();
323
324 // this ensures that target is not nulled, as all other appends are NC-versions
325 target._("");
327
328 while ( format.IsNotEmpty() )
329 {
330 // read n equal characters
331 int n= 1;
332 character c= format.ConsumeChar();
333 while ( format.ConsumeChar(c) )
334 ++n;
335
336 switch (c)
337 {
338 case '\'': // single quotes
339 {
340 // one or more pairs of single quotes?
341 if ( n > 1 )
342 {
343 int pairs= n / 2;
344 target.InsertChars<NC>( '\'', pairs );
345 n-= (pairs * 2);
346 }
347
348 // one single quote?
349 if ( n == 1 )
350 {
351 // search end
352 integer end= format.IndexOf( '\'' );
353 if ( end < 1 )
354 {
355 ALIB_WARNING( "ALIB", "Format Error: Missing single Quote" )
356 target << "Format Error: Missing closing single quote character <'>" ;
357 return target;
358 }
359
360 target._<NC>( format, 0, end );
361 format.ConsumeChars<NC>( end + 1 );
362 }
363
364 } break;
365
366 case 's': // second
367 target.template _<NC>( alib::Dec( Second, n, nf ) );
368 break;
369
370 case 'm': //minute
371 target._<NC>( alib::Dec( Minute, n, nf ) );
372 break;
373
374 case 'K': // hour 0..11
375 target._<NC>( alib::Dec( Hour % 12, n, nf ) );
376 target._<NC>( Hour < 12 ? " am" : " pm" );
377 break;
378
379 case 'H': // hour 0..23
380 target._<NC>( alib::Dec( Hour, n, nf ) );
381 break;
382
383 case 'd': // day
384 if ( n <= 2 ) target._<NC>( alib::Dec( Day, n, nf) );
385 else if ( n == 3 ) target._<NC>( DAY_NAMES[DayOfWeek], 0, 3 );
386 else target._<NC>( DAY_NAMES[DayOfWeek] );
387 break;
388
389 case 'M': // month
390 if ( n <= 2 ) target._<NC>( alib::Dec( Month, n, nf ) );
391 else if ( n == 3 ) target._<NC>( MONTH_NAMES[Month-1], 0, 3 );
392 else target._<NC>( MONTH_NAMES[Month-1] );
393 break;
394
395 case 'y': // year
396 if ( n == 1 ) target._<NC>( alib::Dec(Year, 1, nf) );
397 else if ( n == 2 ) target._<NC>( alib::Dec(Year % 100, 2, nf) );
398 else target._<NC>( alib::Dec(Year, n, nf) );
399 break;
400
401 default: // otherwise: copy what was in
402 target.InsertChars<NC>( c, n );
403 break;
404 }
405
406 }
407
408 return target;
409}
410
411
412
413} // namespace [ alib::system]
TAString & InsertChars(TChar c, integer qty)
TAString & _(const TAppendable &src)
int Minute
The calendar minute (0..59).
Definition calendar.inl:62
ALIB_DLL void Set(const DateTime &timeStamp, lang::Timezone timezone=lang::Timezone::Local)
Definition calendar.cpp:75
int Second
The calendar second (0..59).
Definition calendar.inl:65
int Day
The calendar day (1..31).
Definition calendar.inl:56
ALIB_DLL AString & Format(Substring format, AString &target, lang::CurrentData targetData=lang::CurrentData::Keep) const
Definition calendar.cpp:319
int Hour
The calendar hour (0..23).
Definition calendar.inl:59
static ALIB_DLL String MONTH_NAMES[12]
Definition calendar.inl:39
int Year
The calendar year (e.g., 2022).
Definition calendar.inl:50
ALIB_DLL DateTime Get(lang::Timezone timezone=lang::Timezone::Local) const
Definition calendar.cpp:117
ALIB_DLL void Clear()
Sets all public values to 0.
Definition calendar.cpp:63
static ALIB_DLL String DAY_NAMES[7]
Definition calendar.inl:47
int Month
The calendar month (1..12).
Definition calendar.inl:53
int Millisecond
The calendar millisecond (0..999).
Definition calendar.inl:68
CalendarDate()=default
Default constructor leaving this object uninitialized (random value). **************.
ALIB_DLL void Set(int year, int month, int day, int dayOfWeek=-1)
Definition calendar.cpp:223
ALIB_DLL CalendarDate operator++()
Definition calendar.cpp:265
uint32_t stamp
Encoded date value.
Definition calendar.inl:357
ALIB_DLL DateTime Get(lang::Timezone timezone=lang::Timezone::Local, int hour=12, int minute=0, int second=0) const
Definition calendar.cpp:252
ALIB_DLL CalendarDate operator+(int daysToAdd) const
Definition calendar.cpp:257
ALIB_DLL CalendarDate operator--()
Definition calendar.cpp:298
int Seconds
The number of seconds (not the total, hence 0-59) within the duration.
Definition calendar.inl:211
ALIB_DLL void FromNanoSeconds(int64_t nanos)
Definition calendar.cpp:189
int Hours
The number of hours (not the total, hence 0-23) within the duration.
Definition calendar.inl:205
int Nanoseconds
The number of nanoseconds (not the total, hence 0-999) within the duration.
Definition calendar.inl:220
int Minutes
The number of minutes (not the total, hence 0-59) within the duration.
Definition calendar.inl:208
int Milliseconds
The number of milliseconds (not the total, hence 0-999) within the duration.
Definition calendar.inl:214
ALIB_DLL void Clear()
Sets all public values to 0.
Definition calendar.cpp:171
int Microseconds
The number of microseconds (not the total, hence 0-999) within the duration.
Definition calendar.inl:217
int Days
The number of days within the duration.
Definition calendar.inl:202
time_t InEpochSeconds() const
Definition datetime.inl:56
static ALIB_DLL DateTime FromSystemTime(const SYSTEMTIME &systemTime, lang::Timezone timezone=lang::Timezone::Local)
ALIB_DLL SYSTEMTIME ToSystemTime(lang::Timezone timezone=lang::Timezone::Local) const
static DateTime FromEpochSeconds(time_t epochSeconds)
Definition datetime.inl:70
#define A_CHAR(STR)
#define ALIB_WARNING(domain,...)
Definition alib.inl:1046
#define ALIB_ASSERT_ERROR(cond, domain,...)
Definition alib.inl:1049
@ Clear
Chooses to clear existing data.
Timezone
Denotes whether a time value represents local time or UTC.
@ UTC
Denotes UTC (coordinated universal time).
strings::TDec< character > Dec
Type alias in namespace alib.
Definition format.inl:545
strings::TAString< character, lang::HeapAllocator > AString
Type alias in namespace alib.
time::DateTime DateTime
Type alias in namespace alib.
Definition datetime.inl:224
lang::integer integer
Type alias in namespace alib.
Definition integers.inl:149
strings::TNumberFormat< character > NumberFormat
Type alias in namespace alib.
strings::util::CalendarDateTime CalendarDateTime
Type alias in namespace alib.
Definition calendar.inl:647
strings::TString< character > String
Type alias in namespace alib.
Definition string.inl:2381
characters::character character
Type alias in namespace alib.
strings::TSubstring< character > Substring
Type alias in namespace alib.