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