OWLNext    7.0
Borland's Object Windows Library for the modern age
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
date.cpp
Go to the documentation of this file.
1//----------------------------------------------------------------------------
2// ObjectWindows
3// Copyright (c) 1993, 1997 by Borland International, All Rights Reserved
4//
5/// \file
6/// TDate class implementation
7//----------------------------------------------------------------------------
8#include <owl/pch.h>
9#include <owl/date.h>
10#include <owl/time.h>
11#include <owl/profile.h>
12#include <owl/wsyscls.h>
13
14#include <stdio.h>
15#include <time.h>
16#include <string.h>
17#include <ctype.h>
18#include <tchar.h>
19
20namespace owl {
21
22/****************************************************************
23 * *
24 * static constants *
25 * *
26 ****************************************************************/
27
28const uint32 SECONDS_IN_DAY = 86400L;
29
30
31static const _TUCHAR sDaysInMonth[12] =
32 { 31,28,31,30,31,30,31,31,30,31,30,31 };
33static const DayTy sFirstDayOfEachMonth[12] =
34 { 1,32,60,91,121,152,182,213,244,274,305,335 };
35
36// default names
37static const tchar* DefMonthNames[12] =
38 { _T("January"),_T("February"),_T("March"),_T("April"),_T("May"),_T("June"),
39 _T("July"),_T("August"),_T("September"),_T("October"),_T("November"),_T("December") };
40static const tchar* DefUCMonthNames[12] =
41 { _T("JANUARY"),_T("FEBRUARY"),_T("MARCH"),_T("APRIL"),_T("MAY"),_T("JUNE"),
42 _T("JULY"),_T("AUGUST"),_T("SEPTEMBER"),_T("OCTOBER"),_T("NOVEMBER"),_T("DECEMBER") };
43
44static const tchar* DefWeekDayNames[7] =
45 { _T("Monday"),_T("Tuesday"),_T("Wednesday"),
46 _T("Thursday"),_T("Friday"),_T("Saturday"),_T("Sunday") };
47static const tchar* DefUCWeekDayNames[7] =
48 { _T("MONDAY"),_T("TUESDAY"),_T("WEDNESDAY"),
49 _T("THURSDAY"),_T("FRIDAY"),_T("SATURDAY"),_T("SUNDAY") };
50
51
52static const tchar** MonthNames = DefMonthNames;
53static const tchar** UCMonthNames = DefUCMonthNames;
54static const tchar** WeekDayNames = DefWeekDayNames;
55static const tchar** UCWeekDayNames = DefUCWeekDayNames;
56
57_OWLSTATICFUNC(static int) FindMatch( const tchar *str, const tchar**candidates, int icand );
58
59/***************************************************************************/
60
61// constructors
62
63/***************************************************************************/
64
65//
66/// Constructs a TDate object with the current date.
67//
69{
70 //long clk = time(0);
71 //struct tm *now = localtime(&clk);
72 // We no longer need to default to adding 1900 - (GSF) ???????????
73 //long _Julnum = Jday(now->tm_mon+1, now->tm_mday, now->tm_year+1900);
75 Julnum = Jday( _clk.GetMonth(), _clk.GetDay(), _clk.GetYear());
76}
77
78//
79/// Constructs a TDate object with the given day and year. The base date for
80/// this computation is December 31 of the previous year. If year == 0, it
81/// constructs a TDate with January 1, 1901, as the "day zero." For example,
82/// TDate(-1,0) = December 31, 1900, and TDate(1,0) = January 2, 1901.
83//
85{
86 if( year )
87 Julnum = Jday( 12, 31, year-1 ) + static_cast<JulTy>(day);
88 else
89 Julnum = jul1901 + static_cast<JulTy>(day);
90}
91
92//
93/// Construct a TDate for the given day, monthName, and year.
94//
99
100//
101/// Construct a TDate for the given day, month, and year.
102//
104{
105 Julnum = Jday( month, day, year );
106}
107
108//
109/// Type conversion to date.
110//
111TDate::TDate( const TTime & t )
112{
113 Julnum = t.IsValid() ? jul1901 + static_cast<JulTy>(t.LocalSecs()/SECONDS_IN_DAY) : 0;
114}
115
116//
117/// Construct a TDate from a TSystemTime
118//
120{
121 Julnum = Jday( t.GetMonth(), t.GetDay(), t.GetYear());
122}
123
124//
125//
126//
129{
130 MonthTy m; DayTy d; YearTy y;
131 Mdy(m, d, y);
132 return TSystemTime(y, m, d, 0, 0, 0, WeekDay());
133}
134
135/***************************************************************************/
136
137// static member functions
138
139/***************************************************************************/
140
141//
142/// Returns a string name for the weekday number.
143/// Monday == 1, ... , Sunday == 7
144/// Return 0 for weekday number out of range
145//
147{
148 return AssertWeekDayNumber(weekDayNumber) ? WeekDayNames[weekDayNumber-1] : nullptr;
149}
150
151//
152/// Return the number, 1-7, of the day of the week named nameOfDay.
153/// Return 0 if name doesn't match.
154//
156{
157 return static_cast<DayTy>(FindMatch( nameOfDay.c_str(), UCWeekDayNames, 7 )+1);
158}
159
160// Return the number of days of a given month
161// Return 0 if "month" is outside of the range 1 through 12, inclusive.
163{
164 uint days = 0;
165
166 if (month == 0)
167 month = Month();
168
170 days = sDaysInMonth[month-1];
171 if(Leap() && month == 2)
172 days++;
173 }
174
175 return days;
176}
177
178//
179/// Returns 1 if the given day (1-31) is within the given month for the given year.
180//
182{
183 if( day <= 0 || !AssertIndexOfMonth(month) )
184 return 0;
185 unsigned d = sDaysInMonth[month-1];
186 if( LeapYear(year) && month == 2 )
187 d++;
188 return day <= d;
189}
190
191//
192/// Returns the number of days in the year specified (365 or 366).
193//
195{
196 return LeapYear(year) ? 366 : 365;
197}
198
199//
200/// Returns the number, 1-12, of the month named nameOfMonth.
201/// Return 0 for no match.
202//
204{
205 return static_cast<MonthTy>(FindMatch(nameOfMonth.c_str(), UCMonthNames, 12 )+1);
206}
207
208//
209/// Convert Gregorian calendar date to the corresponding Julian day
210/// number j. Algorithm 199 from Communications of the ACM, Volume 6, No.
211/// 8, (Aug. 1963), p. 444. Gregorian calendar started on Sep. 14, 1752.
212/// This function not valid before that.
213/// Returns 0 if the date is invalid.
214//
216{
217 uint32 c, ya;
218 // We now always default to adding 1900 like the TDate CTOR - (GSF)
219 // if( y <= 99 ).
220 if( y <= 137 ) // year 2037 problem (long overflow)
221 y += 1900;
222 if( !DayWithinMonth(m, d, y) )
223 return static_cast<JulTy>(0);
224
225 if( m > 2 )
226 m -= 3;
227 else{
228 m += 9;
229 y--;
230 }
231
232 c = y / 100;
233 ya = y - 100*c;
234 return ((146097L*c)>>2) + ((1461*ya)>>2) + (153*m + 2)/5 + d + 1721119L;
235}
236
237//
238// Algorithm from K & R, "The C Programming Language", 1st ed.
239//
241{
242 return ((year & 3) == 0 && (year % 100) != 0) || (year % 400) == 0;
243}
244
245//
246/// Returns the string name for the given monthNumber (1-12). Returns 0 for an
247/// invalid monthNumber.
248//
250{
251 return AssertIndexOfMonth(monthNumber) ? MonthNames[monthNumber-1] : nullptr;
252}
253
254//
255// Return index of case-insensitive match; -1 if no match.
256//
257_OWLSTATICFUNC(static int)
258FindMatch( const tchar* str, const tchar** candidates, int icand )
259{
260 unsigned len = static_cast<unsigned>(::_tcslen(str));
261
262 while(icand--){
263 if( _tcsnicmp(str, candidates[icand], len) == 0)
264 break;
265 }
266 return icand;
267}
268
269/****************************************************************
270 * *
271 * Member functions *
272 * *
273 ****************************************************************/
274
275//
276/// Returns 1 if the target TDate is greater than parameter TDate, -1 if the target
277/// is less than the parameter, and 0 if the dates are equal.
278//
279int TDate::CompareTo( const TDate &d ) const
280{
281 if( Julnum < d.Julnum )
282 return -1;
283 else if( Julnum > d.Julnum )
284 return 1;
285 else
286 return 0;
287}
288
289//
290/// Returns the day of the year (1-365).
291//
293{
294 return DayTy(Julnum - Jday( 12, 31, Year()-1 ));
295}
296
297//
298/// Returns the day (1-31) of the month of this TDate.
299//
301{
302 MonthTy m; DayTy d; YearTy y;
303 Mdy( m, d, y );
304 return d;
305}
306
307//
308/// Return the number of the first day of a given month
309/// Return 0 if "month" is outside of the range 1 through 12, inclusive.
310//
312{
314 return 0;
315 unsigned firstDay = sFirstDayOfEachMonth[month-1];
316 if (month > 2 && Leap())
317 firstDay++;
318 return firstDay;
319}
320
321/// Returns a hash value for the date.
322unsigned TDate::Hash() const
323{
324 return static_cast<unsigned>(Julnum);
325}
326
327//
328/// Convert a Julian day number to its corresponding Gregorian calendar
329/// date. Algorithm 199 from Communications of the ACM, Volume 6, No. 8,
330/// (Aug. 1963), p. 444. Gregorian calendar started on Sep. 14, 1752.
331/// This function not valid before that.
332//
333_OWLSTATICFUNC(void)
334TDate::Mdy( MonthTy & m, DayTy & d, YearTy & y ) const
335{
336 uint32 _d;
337 JulTy j = Julnum - 1721119L;
338 y = (YearTy) (((j<<2) - 1) / 146097L);
339 j = (j<<2) - 1 - 146097L*y;
340 _d = (j>>2);
341 j = ((_d<<2) + 3) / 1461;
342 _d = (_d<<2) + 3 - 1461*j;
343 _d = (_d + 4)>>2;
344 m = (MonthTy)(5*_d - 3)/153;
345 _d = 5*_d - 3 - 153*m;
346 d = (DayTy)((_d + 5)/5);
347 y = (YearTy)(100*y + j);
348
349 if( m < 10 )
350 m += 3;
351 else{
352 m -= 9;
353 y++;
354 }
355}
356
357//
358/// Compares this TDate with dt and returns the date with the greater Julian number.
359//
360TDate
361TDate::Max( const TDate & dt ) const
362{
363 return dt.Julnum > Julnum ? dt : *this;
364}
365
366//
367/// Compares this TDate with dt and returns the date with the lesser Julian number.
368//
369TDate
370TDate::Min( const TDate & dt ) const
371{
372 return dt.Julnum < Julnum ? dt : *this;
373}
374
375//
376/// Returns the month of this TDate.
377//
380{
381 MonthTy m; DayTy d; YearTy y;
382 Mdy(m, d, y);
383 return m;
384}
385
386//
387/// Returns the TDate of the previous dayName.
388//
389TDate
391{
392 return Previous( DayOfWeek(dayName) );
393}
394
395//
396/// Returns the TDate of the previous day.
397//
398TDate
400{
401 // Renumber the desired and current day of week to start at 0 (Monday)
402 // and end at 6 (Sunday).
403
406 JulTy j = Julnum;
407
408 // Have to determine how many days difference from current day back to
409 // desired, if any. Special calculation under the 'if' statement to
410 // effect the wraparound counting from Monday (0) back to Sunday (6).
413 else
415 j -= thisDayOfWeek; // Adjust j to set it at the desired day of week.
416 return TDate(j);
417}
418
419//
420/// Returns 1 (Monday) through 7 (Sunday).
421//
423{
424 JulTy julnum = (day == 0 ? Julnum : Jday(day, Month(), Year()));
425 return DayTy(((((julnum+1)%7)+6)%7)+1);
426}
427
428//
429/// Returns the year of this TDate.
430//
432{
433 MonthTy m; DayTy d; YearTy y;
434 Mdy(m, d, y);
435 return y;
436}
437
438namespace
439{
440
441 int accept_digits(LPCTSTR str)
442 {
443 int n = 0;
444 while (_istdigit(str[n]))
445 n++;
446 return n;
447 }
448
450 {
451 int n = 0;
452 while (_totlower(picture[n]) == c)
453 n++;
454 return n;
455 }
456
458 {
459 const int n = accept_digits(str);
460 int result = _ttoi(tstring(str, 0, n).c_str());
461 str += n;
463 return result;
464 }
465
466} // namespace
467
468//
469/// Convert a string to a date according to the [Intl] section in win.ini or the
470/// passed format specifier
471void TDate::ParseFrom(LPCTSTR str, LPCTSTR format)
472{
473 int day, month, year;
474 Julnum = day = month = year = 0;
475
476 TProfile p(_T("intl"));
477 tstring shortFmt = p.GetString(_T("sShortDate"), _T("MM/dd/yyyy"));
478 LPCTSTR picture = format ? format : shortFmt.c_str();
479
480 while (*picture && *str) {
481 tchar c = static_cast<tchar>(_totlower(*picture));
482 switch (c) {
483 case _T('d'): {
484 day = parse_number(str, picture, c);
485 break;
486 }
487 case _T('m'): {
488 month = parse_number(str, picture, c);
489 break;
490 }
491 case _T('y'): {
492 year = parse_number(str, picture, c);
493 break;
494 }
495 default: {
496 picture++;
497 str++;
498 }
499 }
500 }
501
502 Julnum = Jday(month, day, year);
503 if (Julnum < 1)
504 Julnum = 0;
505}
506
507//
508//
509//
510void
512{
513 const tchar*** Names[] = { &MonthNames, &UCMonthNames,
514 &WeekDayNames, &UCWeekDayNames,
515 };
516 const tchar*** DefNames[] = {
517 (const tchar***)&DefMonthNames, (const tchar***)&DefUCMonthNames,
518 (const tchar***)&DefWeekDayNames, (const tchar***)&DefUCWeekDayNames,
519 };
520 if(names)
521 *(Names[type]) = names;
522 else
523 *(Names[type]) = *(DefNames[type]);
524}
525
526//
527//
528//
529const tchar*
531{
532 const tchar** Names[] = { MonthNames, UCMonthNames,
533 WeekDayNames, UCWeekDayNames,
534 };
535 return Names[type][index];
536}
537
538//
539/// Returns a new TDate containing the sum of this TDate and dd.
540//
542{
543 return TDate(dt.Julnum + dd);
544}
545
546//
547/// Returns a new TDate containing the sum of this TDate and dd.
548//
550{
551 return TDate(dt.Julnum + dd);
552}
553
554//
555//
556//
558{
559 return TDate(dt.Julnum - dd);
560}
561
562//
563//
564//
565} // OWL namespace
566/* ========================================================================== */
The TDate class represents a date.
Definition date.h:48
YearTy Year() const
Returns the year of this TDate.
Definition date.cpp:431
static int LeapYear(YearTy year)
Definition date.cpp:240
unsigned Hash() const
Returns a hash value for the date.
Definition date.cpp:322
int DaysInMonth(MonthTy month=0) const
Definition date.cpp:162
TDate()
Construct a TDate with the current date.
Definition date.cpp:68
static LPCTSTR MonthName(MonthTy monthNumber)
Returns the string name for the given monthNumber (1-12).
Definition date.cpp:249
static int AssertIndexOfMonth(MonthTy m)
Returns 1 if m is between 1 and 12 inclusive, otherwise returns 0.
Definition date.h:308
int Leap() const
leap year?
Definition date.h:218
static DayTy DaysInYear(YearTy)
Returns the number of days in the year specified (365 or 366).
Definition date.cpp:194
TDate Max(const TDate &dt) const
Compares this TDate with dt and returns the date with the greater Julian number.
Definition date.cpp:361
int CompareTo(const TDate &) const
Returns 1 if the target TDate is greater than parameter TDate, -1 if the target is less than the para...
Definition date.cpp:279
static int AssertWeekDayNumber(DayTy d)
Returns 1 if d is between 1 and 7 inclusive, otherwise returns 0.
Definition date.h:302
static MonthTy IndexOfMonth(const tstring &monthName)
Returns the number, 1-12, of the month named nameOfMonth.
Definition date.cpp:203
static LPCTSTR DayName(DayTy weekDayNumber)
Returns a string name for the weekday number.
Definition date.cpp:146
DayTy FirstDayOfMonth() const
Returns the number of the first day of the month for this TDate.
Definition date.h:206
static void SetIntlNames(TDateType type, const tchar **names)
Definition date.cpp:511
static const tchar * GetIntlName(TDateType type, int index)
Definition date.cpp:530
MonthTy Month() const
Returns the month of this TDate.
Definition date.cpp:379
TSystemTime GetSystemTime() const
Definition date.cpp:128
static int DayWithinMonth(MonthTy, DayTy, YearTy)
Returns 1 if the given day (1-31) is within the given month for the given year.
Definition date.cpp:181
DayTy WeekDay(DayTy day=0) const
Returns 1 (Monday) through 7 (Sunday).
Definition date.cpp:422
TDate Min(const TDate &dt) const
Compares this TDate with dt and returns the date with the lesser Julian number.
Definition date.cpp:370
static DayTy DayOfWeek(const tstring &dayName)
Return the number, 1-7, of the day of the week named nameOfDay.
Definition date.cpp:155
DayTy Day() const
Returns the day of the year (1-365).
Definition date.cpp:292
static JulTy Jday(MonthTy, DayTy, YearTy)
Convert Gregorian calendar date to the corresponding Julian day number j.
Definition date.cpp:215
TDate Previous(const tstring &dayName) const
Return date of previous dayName.
Definition date.cpp:390
DayTy DayOfMonth() const
Returns the day (1-31) of the month of this TDate.
Definition date.cpp:300
TSystemTime is a class derived from the structure SYSTEMTIME.
Definition wsyscls.h:420
uint16 GetDay()
Definition wsyscls.h:447
uint16 GetMonth()
Definition wsyscls.h:439
static TSystemTime LocalTime()
Definition wsyscls.h:468
uint16 GetYear()
Definition wsyscls.h:435
The TTime class encapsulates time functions and characteristics.
Definition time.h:38
int IsValid() const
Returns 1 if this TTime object contains a valid time, 0 otherwise.
Definition time.h:126
#define _istdigit
Definition cygwin.h:70
#define _ttoi
Definition cygwin.h:64
#define _tcsnicmp
Definition cygwin.h:77
#define _tcslen
Definition cygwin.h:74
unsigned char _TUCHAR
Definition cygwin.h:44
#define _T(x)
Definition cygwin.h:51
Object Windows Library (OWLNext Core)
Definition animctrl.h:22
const uint32 SECONDS_IN_DAY
Definition date.cpp:28
unsigned long uint32
Definition number.h:34
unsigned YearTy
Year type.
Definition date.h:32
char tchar
Definition defs.h:77
TTime operator+(const TTime &t, long s)
Adds s seconds to time t.
Definition time.h:180
TTime operator-(const TTime &t, long s)
Performs subtraction, in seconds, between s and t.
Definition time.h:192
unsigned long JulTy
Julian calendar type.
Definition date.h:35
FindMatch(const tchar *str, const tchar **candidates, int icand)
Definition date.cpp:258
std::string tstring
Definition defs.h:79
unsigned DayTy
Day type.
Definition date.h:26
const tchar ** candidates
Definition date.cpp:57
unsigned MonthTy
Month type.
Definition date.h:29
const tchar int icand
Definition date.cpp:57
#define _OWLSTATICFUNC(p)
Definition defs.h:308
#define _OWLFUNC(p)
Definition defs.h:341
Definition of TProfile class.
Definition of class TString, a flexible universal string envelope class.
Classes for window system structure and type encapsulation.