home *** CD-ROM | disk | FTP | other *** search
- {$INCLUDE ..\cDefines.inc}
- unit cDateTime;
-
- interface
-
- uses
- // Delphi
- SysUtils;
-
-
-
- { }
- { DateTime functions v3.08 }
- { }
- { A collection of date/time functions. }
- { }
- { }
- { This unit is copyrighted ⌐ 1999-2002 by David Butler (david@e.co.za) }
- { }
- { This unit is part of Delphi Fundamentals. }
- { Its original file name is cDateTime.pas }
- { The latest version is available from the Fundamentals home page }
- { http://fundementals.sourceforge.net/ }
- { }
- { I invite you to use this unit, free of charge. }
- { I invite you to distibute this unit, but it must be for free. }
- { I also invite you to contribute to its development, }
- { but do not distribute a modified copy of this file. }
- { }
- { A forum is available on SourceForge for general discussion }
- { http://sourceforge.net/forum/forum.php?forum_id=2117 }
- { }
- { }
- { Notes: }
- { A good source of information on calendars is the FAQ ABOUT CALENDARS, }
- { available at http://www.tondering.dk/claus/calendar.html }
- { }
- { Note the following (and more) is available in SysUtils: }
- { Function IsLeapYear (Year : Word) : Boolean }
- { (1 = Sunday .. 7 = Saturday) }
- { Function EncodeDate (Year, Month, Day : Word) : TDateTime; }
- { Procedure DecodeDate (D : DateTime; var Year, Month, Day : Word); }
- { var ShortDayNames, LongDayNames, ShortMonthNames, LongMonthNames : Array }
- { }
- { }
- { Revision history: }
- { 1999/11/10 0.01 Initial version from scratch. Add functions. DayOfYear. }
- { 1999/11/21 0.02 EasterSunday function. Diff functions. ISOInteger. }
- { 2000/03/04 1.03 Moved RFC functions to cInternetStandards. }
- { 2000/03/05 1.04 Added Time Zone functions from cInternetStandards. }
- { 2000/05/03 1.05 Added ISO Week functions, courtesy of Martin Boonstra }
- { <m.boonstra@imn.nl> }
- { 2000/08/16 1.06 Fixed bug in GMTBias reported by Gerhard Steinwedel }
- { <steinwedel@gmx.de> }
- { 2001/12/22 2.07 Added RFC DateTime functions from cInternetStandards. }
- { 2002/01/10 3.08 Fixed bug with negative values in AddMonths as }
- { reported by Michael Valentiner <MichaelVB@gmx.de> }
- { }
-
- const
- UnitName = 'cDateTime';
- UnitVersion = '3.08';
- UnitDesc = 'Date/Time functions';
-
-
- type
- EDateTime = class (Exception);
-
-
-
- { }
- { Decoding }
- { }
- {$IFNDEF DELPHI6_UP}
- Procedure DecodeDateTime (const DateTime : TDateTime; var Year, Month, Day, Hour, Minute, Second, Millisecond : Word);
- {$ENDIF}
- Function Century (const D : TDateTime) : Word;
- Function Year (const D : TDateTime) : Word;
- Function Month (const D : TDateTime) : Word;
- Function Day (const D : TDateTime) : Word;
- Function Hour (const D : TDateTime) : Word;
- Function Minute (const D : TDateTime) : Word;
- Function Second (const D : TDateTime) : Word;
- Function Millisecond (const D : TDateTime) : Word;
-
- const
- OneDay = 1.0;
- OneHour = OneDay / 24.0;
- OneMinute = OneHour / 60.0;
- OneSecond = OneMinute / 60.0;
- OneMillisecond = OneSecond / 1000.0;
-
-
-
- { }
- { Encoding }
- { }
- {$IFNDEF DELPHI6_UP}
- Function EncodeDateTime (const Year, Month, Day, Hour, Minute, Second, Millisecond : Word) : TDateTime;
- {$ENDIF}
- Procedure SetYear (var D : TDateTime; const Year : Word);
- Procedure SetMonth (var D : TDateTime; const Month : Word);
- Procedure SetDay (var D : TDateTime; const Day : Word);
- Procedure SetHour (var D : TDateTime; const Hour : Word);
- Procedure SetMinute (var D : TDateTime; const Minute : Word);
- Procedure SetSecond (var D : TDateTime; const Second : Word);
- Procedure SetMillisecond (var D : TDateTime; const Milliseconds : Word);
-
-
-
- { }
- { Comparison }
- { }
- Function IsEqual (const D1, D2 : TDateTime) : Boolean; overload;
- Function IsEqual (const D1 : TDateTime; const Ye, Mo, Da : Word) : Boolean; overload;
- Function IsEqual (const D1 : TDateTime; const Ho, Mi, Se, ms : Word) : Boolean; overload;
- Function IsAM (const D : TDateTime) : Boolean;
- Function IsPM (const D : TDateTime) : Boolean;
- Function IsMidnight (const D : TDateTime) : Boolean;
- Function IsNoon (const D : TDateTime) : Boolean;
- Function IsSunday (const D : TDateTime) : Boolean;
- Function IsMonday (const D : TDateTime) : Boolean;
- Function IsTuesday (const D : TDateTime) : Boolean;
- Function IsWedneday (const D : TDateTime) : Boolean;
- Function IsThursday (const D : TDateTime) : Boolean;
- Function IsFriday (const D : TDateTime) : Boolean;
- Function IsSaturday (const D : TDateTime) : Boolean;
- Function IsWeekend (const D : TDateTime) : Boolean;
-
-
-
- { }
- { Relative date/times }
- { }
- Function Noon (const D : TDateTime) : TDateTime;
- Function Midnight (const D : TDateTime) : TDateTime;
- Function FirstDayOfMonth (const D : TDateTime) : TDateTime;
- Function LastDayOfMonth (const D : TDateTime) : TDateTime;
- Function NextWorkday (const D : TDateTime) : TDateTime;
- Function PreviousWorkday (const D : TDateTime) : TDateTime;
- Function FirstDayOfYear (const D : TDateTime) : TDateTime;
- Function LastDayOfYear (const D : TDateTime) : TDateTime;
- Function EasterSunday (const Year : Word) : TDateTime;
- Function GoodFriday (const Year : Word) : TDateTime;
-
- Function AddMilliseconds (const D : TDateTime; const N : Int64) : TDateTime;
- Function AddSeconds (const D : TDateTime; const N : Int64) : TDateTime;
- Function AddMinutes (const D : TDateTime; const N : Integer) : TDateTime;
- Function AddHours (const D : TDateTime; const N : Integer) : TDateTime;
- Function AddDays (const D : TDateTime; const N : Integer) : TDateTime;
- Function AddWeeks (const D : TDateTime; const N : Integer) : TDateTime;
- Function AddMonths (const D : TDateTime; const N : Integer) : TDateTime;
- Function AddYears (const D : TDateTime; const N : Integer) : TDateTime;
-
-
-
- { }
- { Counting }
- { }
- { DayOfYear and WeekNumber start at 1. }
- { WeekNumber is not the ISO week number but the week number where week one }
- { starts at Jan 1. }
- { For reference: ISO standard 8601:1988 - (European Standard EN 28601). }
- { "It states that a week is identified by its number in a given year. }
- { A week begins with a Monday (day 1) and ends with a Sunday (day 7). }
- { The first week of a year is the one which includes the first Thursday }
- { (day 4), or equivalently the one which includes January 4. }
- { In other words, the first week of a new year is the week that has the }
- { majority of its days in the new year." }
- { ISOFirstWeekOfYear returns the start date (Monday) of the first ISO week }
- { of a year (may be in the previous year). }
- { ISOWeekNumber returns the ISO Week number and the year to which the week }
- { number applies. }
- { }
- Function DayOfYear (const Ye, Mo, Da : Word) : Integer; overload;
- Function DayOfYear (const D : TDateTime) : Integer; overload;
- Function DaysInMonth (const Ye, Mo : Word) : Integer; overload;
- Function DaysInMonth (const D : TDateTime) : Integer; overload;
- Function DaysInYear (const Ye : Word) : Integer; overload;
- Function DaysInYear (const D : TDateTime) : Integer; overload;
- Function WeekNumber (const D : TDateTime) : Integer;
- Function ISOFirstWeekOfYear (const Ye : Integer) : TDateTime;
- Procedure ISOWeekNumber (const D : TDateTime; var WeekNumber, WeekYear : Word);
- Function DateTimeAsISO8601String (const D : TDateTime) : String;
- Function ISO8601StringAsDateTime (const D : String) : TDateTime;
-
-
-
- { }
- { Difference }
- { }
- Function DiffMilliseconds (const D1, D2 : TDateTime) : Int64;
- Function DiffSeconds (const D1, D2 : TDateTime) : Integer;
- Function DiffMinutes (const D1, D2 : TDateTime) : Integer;
- Function DiffHours (const D1, D2 : TDateTime) : Integer;
- Function DiffDays (const D1, D2 : TDateTime) : Integer;
- Function DiffWeeks (const D1, D2 : TDateTime) : Integer;
- Function DiffMonths (const D1, D2 : TDateTime) : Integer;
- Function DiffYears (const D1, D2 : TDateTime) : Integer;
-
-
-
- { }
- { Time Zone }
- { Uses systems regional settings to convert between local and GMT time. }
- { }
- Function GMTTimeToLocalTime (const D : TDateTime) : TDateTime;
- Function LocalTimeToGMTTime (const D : TDateTime) : TDateTime;
-
-
-
- { }
- { Conversions }
- { }
- { ANSI Integer is an integer in the format YYYYDDD (where DDD = day number) }
- { ISO-8601 Integer date is an integer in the format YYYYMMDD. }
- { TropicalYear is the time for one orbit of the earth around the sun. }
- { TwoDigitYearToYear returns the full year number given a two digit year. }
- { SynodicMonth is the time between two full moons. }
- { }
- Function DateTimeToANSI (const D : TDateTime) : Integer;
- Function ANSIToDateTime (const Julian : Integer) : TDateTime;
- Function DateTimeToISOInteger (const D : TDateTime) : Integer;
- Function DateTimeToISO (const D : TDateTime) : String;
- Function ISOIntegerToDateTime (const ISOInteger : Integer) : TDateTime;
- Function TwoDigitYearToYear (const Y : Integer) : Integer;
- Function DateTimeAsElapsedTime (const D : TDateTime) : String;
-
-
-
- { }
- { RFC DateTimes }
- { }
- { RFC1123 DateTime is the preferred representation on the Internet for all }
- { DateTime values. }
- { Use DateTimeToRFCDateTime to convert local time to RFC1123 DateTime. }
- { Use RFCDateTimeToDateTime to convert RFC DateTime formats to local time. }
- { Returns 0.0 if not a recognised RFC DateTime. }
- { See RFC822, RFC850, RFC1123, RFC1036, RFC1945. }
- { }
- { From RFC 822 (Standard for the format of ARPA INTERNET Text Messages): }
- { "time = hour zone ; ANSI and Military }
- { hour = 2DIGIT ":" 2DIGIT [":" 2DIGIT] ; 00:00:00 - 23:59:59 }
- { zone = "UT" / "GMT" ; Universal Time }
- { ; North American : UT }
- { / "EST" / "EDT" ; Eastern: - 5/ - 4 }
- { / "CST" / "CDT" ; Central: - 6/ - 5 }
- { / "MST" / "MDT" ; Mountain: - 7/ - 6 }
- { / "PST" / "PDT" ; Pacific: - 8/ - 7 }
- { / 1ALPHA ; Military: Z = UT; }
- { ; A:-1; (J not used) }
- { ; M:-12; N:+1; Y:+12 }
- { / ( ("+" / "-") 4DIGIT ) ; Local differential }
- { ; hours+min. (HHMM) }
- { date-time = [ day "," ] date time ; dd mm yy }
- { ; hh:mm:ss zzz }
- { day = "Mon" / "Tue" / "Wed" / "Thu" }
- { / "Fri" / "Sat" / "Sun" }
- { date = 1*2DIGIT month 2DIGIT ; day month year }
- { ; e.g. 20 Jun 82 }
- { month = "Jan" / "Feb" / "Mar" / "Apr" }
- { / "May" / "Jun" / "Jul" / "Aug" }
- { / "Sep" / "Oct" / "Nov" / "Dec" " }
- { }
- { Note that even though RFC 822 states hour=2DIGIT":"2DIGIT, none of the }
- { examples given in the appendix include the ":", }
- { for example: "26 Aug 76 1429 EDT" }
- { }
- { }
- { From RFC 1036 (Standard for Interchange of USENET Messages): }
- { }
- { "Its format must be acceptable both in RFC-822 and to the getdate(3) }
- { routine that is provided with the Usenet software. ... }
- { One format that is acceptable to both is: }
- { }
- { Wdy, DD Mon YY HH:MM:SS TIMEZONE }
- { }
- { Note in particular that ctime(3) format: }
- { }
- { Wdy Mon DD HH:MM:SS YYYY }
- { }
- { is not acceptable because it is not a valid RFC-822 date. However, }
- { since older software still generates this format, news }
- { implementations are encouraged to accept this format and translate }
- { it into an acceptable format. " }
- { }
- { "Here is an example of a message in the old format (before the }
- { existence of this standard). It is recommended that }
- { implementations also accept messages in this format to ease upward }
- { conversion. }
- { }
- { Posted: Fri Nov 19 16:14:55 1982 " }
- { }
- { }
- { From RFC 1945 (Hypertext Transfer Protocol -- HTTP/1.0) }
- { }
- { "HTTP/1.0 applications have historically allowed three different }
- { formats for the representation of date/time stamps: }
- { }
- { Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123 }
- { Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036 }
- { Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format }
- { }
- { The first format is preferred as an Internet standard and represents }
- { a fixed-length subset of that defined by RFC 1123 [6] (an update to }
- { RFC 822 [7]). The second format is in common use, but is based on the }
- { obsolete RFC 850 [10] date format and lacks a four-digit year. }
- { HTTP/1.0 clients and servers that parse the date value should accept }
- { all three formats, though they must never generate the third }
- { (asctime) format. }
- { }
- { Note: Recipients of date values are encouraged to be robust in }
- { accepting date values that may have been generated by non-HTTP }
- { applications, as is sometimes the case when retrieving or posting }
- { messages via proxies/gateways to SMTP or NNTP. " }
- { }
- { "All HTTP/1.0 date/time stamps must be represented in Universal Time }
- { (UT), also known as Greenwich Mean Time (GMT), without exception. }
- { }
- { HTTP-date = rfc1123-date | rfc850-date | asctime-date }
- { }
- { rfc1123-date = wkday "," SP date1 SP time SP "GMT" }
- { rfc850-date = weekday "," SP date2 SP time SP "GMT" }
- { asctime-date = wkday SP date3 SP time SP 4DIGIT }
- { }
- { date1 = 2DIGIT SP month SP 4DIGIT }
- { ; day month year (e.g., 02 Jun 1982) }
- { date2 = 2DIGIT "-" month "-" 2DIGIT }
- { ; day-month-year (e.g., 02-Jun-82) }
- { date3 = month SP ( 2DIGIT | ( SP 1DIGIT )) }
- { ; month day (e.g., Jun 2) }
- { }
- { time = 2DIGIT ":" 2DIGIT ":" 2DIGIT }
- { ; 00:00:00 - 23:59:59 }
- { }
- { wkday = "Mon" | "Tue" | "Wed" }
- { | "Thu" | "Fri" | "Sat" | "Sun" }
- { }
- { weekday = "Monday" | "Tuesday" | "Wednesday" }
- { | "Thursday" | "Friday" | "Saturday" | "Sunday" }
- { }
- { month = "Jan" | "Feb" | "Mar" | "Apr" }
- { | "May" | "Jun" | "Jul" | "Aug" }
- { | "Sep" | "Oct" | "Nov" | "Dec" " }
- { }
- Function GMTDateTimeToRFC1123DateTime (const D : TDateTime; const IncludeDayOfWeek : Boolean = True) : String;
- Function DateTimeToRFCDateTime (const D : TDateTime) : String;
- Function NowAsRFCDateTime : String;
-
- Function RFCDateTimeToGMTDateTime (const S : String) : TDateTime;
- Function RFCDateTimeToDateTime (const S : String) : TDateTime;
-
- Function RFCTimeZoneToGMTBias (const Zone : String) : Integer;
-
-
-
- { }
- { High-precision timing }
- { }
- { StartTimer returns an encoded time (running timer). }
- { StopTimer returns an encoded elapsed time (stopped timer). }
- { ResumeTimer returns an encoded time (running timer), given an encoded }
- { elapsed time (stopped timer). }
- { StoppedTimer returns an encoded elapsed time of zero, ie a stopped timer }
- { with no time elapsed. }
- { MillisecondsElapsed returns the time elapsed, given a running or a stopped }
- { Timer. }
- { Times are encoded in CPU clock cycles. }
- { CPU clock frequency returns the number of CPU clock cycles per second. }
- { }
- type
- THPTimer = Int64;
-
- Function StartTimer : THPTimer;
- Procedure StopTimer (var Timer : THPTimer);
- Procedure ResumeTimer (var StoppedTimer : THPTimer);
- Function StoppedTimer : THPTimer;
- Function ElapsedTimer (const Milliseconds : Integer) : THPTimer;
- Function MillisecondsElapsed (const Timer : THPTimer; const TimerRunning : Boolean = True) : Integer;
- Function MicrosecondsElapsed (const Timer : THPTimer; const TimerRunning : Boolean = True) : Integer;
- Function CPUClockFrequency : Int64;
- Procedure DelayMicroSeconds (const MicroSeconds : Integer);
-
-
-
- const
- TropicalYear = 365.24219 * OneDay; // 365 days, 5 hr, 48 min, 46 sec
- SynodicMonth = 29.53059 * OneDay;
-
-
-
- { }
- { Self testing code }
- { }
- Procedure SelfTest;
-
-
-
- implementation
-
-
-
- uses
- // Delphi
- Windows,
- {$IFDEF DELPHI6_UP}
- DateUtils,
- {$ENDIF}
-
- // Fundamentals
- cUtils,
- cStrings;
-
-
-
- { }
- { Decoding }
- { }
- Function Century (const D : TDateTime) : Word;
- Begin
- Result := Year (D) div 100;
- End;
-
- Function Year (const D : TDateTime) : Word;
- var Mo, Da : Word;
- Begin
- DecodeDate (D, Result, Mo, Da);
- End;
-
- Function Month (const D : TDateTime) : Word;
- var Ye, Da : Word;
- Begin
- DecodeDate (D, Ye, Result, Da);
- End;
-
- Function Day (const D : TDateTime) : Word;
- var Ye, Mo : Word;
- Begin
- DecodeDate (D, Ye, Mo, Result);
- End;
-
- Function Hour (const D : TDateTime) : Word;
- var Mi, Se, MS : Word;
- Begin
- DecodeTime (D, Result, Mi, Se, MS);
- End;
-
- Function Minute (const D : TDateTime) : Word;
- var Ho, Se, MS : Word;
- Begin
- DecodeTime (D, Ho, Result, Se, MS);
- End;
-
- Function Second (const D : TDateTime) : Word;
- var Ho, Mi, MS : Word;
- Begin
- DecodeTime (D, Ho, Mi, Result, MS);
- End;
-
- Function Millisecond (const D : TDateTime) : Word;
- var Ho, Mi, Se : Word;
- Begin
- DecodeTime (D, Ho, Mi, Se, Result);
- End;
-
- {$IFNDEF DELPHI6_UP}
- Procedure DecodeDateTime (const DateTime : TDateTime; var Year, Month, Day, Hour, Minute, Second, Millisecond : Word);
- Begin
- DecodeDate (DateTime, Year, Month, Day);
- DecodeTime (DateTime, Hour, Minute, Second, Millisecond);
- End;
-
- Function EncodeDateTime (const Year, Month, Day, Hour, Minute, Second, Millisecond : Word) : TDateTime;
- Begin
- Result := EncodeDate (Year, Month, Day) +
- EncodeTime (Hour, Minute, Second, Millisecond);
- End;
- {$ENDIF}
-
-
-
-
- { }
- { Encoding }
- { }
- Procedure SetYear (var D : TDateTime; const Year : Word);
- var Ye, Mo, Da, Ho, Mi, Se, Ms : Word;
- Begin
- DecodeDateTime (D, Ye, Mo, Da, Ho, Mi, Se, Ms);
- D := EncodeDateTime (Year, Mo, Da, Ho, Mi, Se, Ms);
- End;
-
- Procedure SetMonth (var D : TDateTime; const Month : Word);
- var Ye, Mo, Da, Ho, Mi, Se, Ms : Word;
- Begin
- DecodeDateTime (D, Ye, Mo, Da, Ho, Mi, Se, Ms);
- D := EncodeDateTime (Ye, Month, Da, Ho, Mi, Se, Ms);
- End;
-
- Procedure SetDay (var D : TDateTime; const Day : Word);
- var Ye, Mo, Da, Ho, Mi, Se, Ms : Word;
- Begin
- DecodeDateTime (D, Ye, Mo, Da, Ho, Mi, Se, Ms);
- D := EncodeDateTime (Ye, Mo, Day, Ho, Mi, Se, Ms);
- End;
-
- Procedure SetHour (var D : TDateTime; const Hour : Word);
- var Ye, Mo, Da, Ho, Mi, Se, Ms : Word;
- Begin
- DecodeDateTime (D, Ye, Mo, Da, Ho, Mi, Se, Ms);
- D := EncodeDateTime (Ye, Mo, Da, Hour, Mi, Se, Ms);
- End;
-
- Procedure SetMinute (var D : TDateTime; const Minute : Word);
- var Ye, Mo, Da, Ho, Mi, Se, Ms : Word;
- Begin
- DecodeDateTime (D, Ye, Mo, Da, Ho, Mi, Se, Ms);
- D := EncodeDateTime (Ye, Mo, Da, Ho, Minute, Se, Ms);
- End;
-
- Procedure SetSecond (var D : TDateTime; const Second : Word);
- var Ye, Mo, Da, Ho, Mi, Se, Ms : Word;
- Begin
- DecodeDateTime (D, Ye, Mo, Da, Ho, Mi, Se, Ms);
- D := EncodeDateTime (Ye, Mo, Da, Ho, Mi, Second, Ms);
- End;
-
- Procedure SetMillisecond (var D : TDateTime; const Milliseconds : Word);
- var Ye, Mo, Da, Ho, Mi, Se, Ms : Word;
- Begin
- DecodeDateTime (D, Ye, Mo, Da, Ho, Mi, Se, Ms);
- D := EncodeDateTime (Ye, Mo, Da, Ho, Mi, Se, Milliseconds);
- End;
-
-
-
- { }
- { Comparison }
- { }
- Function IsEqual (const D1, D2 : TDateTime) : Boolean;
- Begin
- Result := Abs (D1 - D2) < OneMillisecond;
- End;
-
- Function IsEqual (const D1 : TDateTime; const Ye, Mo, Da : Word) : Boolean;
- var Ye1, Mo1, Da1 : Word;
- Begin
- DecodeDate (D1, Ye1, Mo1, Da1);
- Result := (Da = Da1) and (Mo = Mo1) and (Ye = Ye1);
- End;
-
- Function IsEqual (const D1 : TDateTime; const Ho, Mi, Se, ms : Word) : Boolean;
- var Ho1, Mi1, Se1, ms1 : Word;
- Begin
- DecodeTime (D1, Ho1, Mi1, Se1, ms1);
- Result := (ms = ms1) and (Se = Se1) and (Mi = Mi1) and (Ho = Ho1);
- End;
-
- Function IsAM (const D : TDateTime) : Boolean;
- Begin
- Result := Frac (D) < 0.5;
- End;
-
- Function IsPM (const D : TDateTime) : Boolean;
- Begin
- Result := Frac (D) >= 0.5;
- End;
-
- Function IsNoon (const D : TDateTime) : Boolean;
- Begin
- Result := Abs (Frac (D) - 0.5) < OneMillisecond;
- End;
-
- Function IsMidnight (const D : TDateTime) : Boolean;
- var T : TDateTime;
- Begin
- T := Frac (D);
- Result := (T < OneMillisecond) or (T > 1.0 - OneMillisecond);
- End;
-
- Function IsSunday (const D : TDateTime) : Boolean;
- Begin
- Result := DayOfWeek (D) = 1;
- End;
-
- Function IsMonday (const D : TDateTime) : Boolean;
- Begin
- Result := DayOfWeek (D) = 2;
- End;
-
- Function IsTuesday (const D : TDateTime) : Boolean;
- Begin
- Result := DayOfWeek (D) = 3;
- End;
-
- Function IsWedneday (const D : TDateTime) : Boolean;
- Begin
- Result := DayOfWeek (D) = 4;
- End;
-
- Function IsThursday (const D : TDateTime) : Boolean;
- Begin
- Result := DayOfWeek (D) = 5;
- End;
-
- Function IsFriday (const D : TDateTime) : Boolean;
- Begin
- Result := DayOfWeek (D) = 6;
- End;
-
- Function IsSaturday (const D : TDateTime) : Boolean;
- Begin
- Result := DayOfWeek (D) = 7;
- End;
-
- Function IsWeekend (const D : TDateTime) : Boolean;
- Begin
- Result := DayOfWeek (D) in [1, 7];
- End;
-
- Function IsWeekday (const D : TDateTime) : Boolean;
- Begin
- Result := DayOfWeek (D) in [2..6];
- End;
-
-
-
- { }
- { Relative calculations }
- { }
- Function Noon (const D : TDateTime) : TDateTime;
- Begin
- Result := Int (D) + 0.5 * OneDay;
- End;
-
- Function Midnight (const D : TDateTime) : TDateTime;
- Begin
- Result := Int (D);
- End;
-
- Function NextWorkday (const D : TDateTime) : TDateTime;
- Begin
- Case DayOfWeek (D) of
- 1..5 : Result := Trunc (D) + OneDay; // 1..5 Sun..Thu
- 6 : Result := Trunc (D) + 3 * OneDay; // 6 Fri
- else Result := Trunc (D) + 2 * OneDay; // 7 Sat
- end;
- End;
-
- Function PreviousWorkday (const D : TDateTime) : TDateTime;
- Begin
- Case DayOfWeek (D) of
- 1 : Result := Trunc (D) - 2 * OneDay; // 1 Sun
- 2 : Result := Trunc (D) - 3 * OneDay; // 2 Mon
- else Result := Trunc (D) - OneDay; // 3..7 Tue-Sat
- end;
- End;
-
- Function LastDayOfMonth (const D : TDateTime) : TDateTime;
- var Ye, Mo, Da : Word;
- Begin
- DecodeDate (D, Ye, Mo, Da);
- Result := EncodeDate (Ye, Mo, DaysInMonth (Ye, Mo));
- End;
-
- Function FirstDayOfMonth (const D : TDateTime) : TDateTime;
- var Ye, Mo, Da : Word;
- Begin
- DecodeDate (D, Ye, Mo, Da);
- Result := EncodeDate (Ye, Mo, 1);
- End;
-
- Function LastDayOfYear (const D : TDateTime) : TDateTime;
- var Ye, Mo, Da : Word;
- Begin
- DecodeDate (D, Ye, Mo, Da);
- Result := EncodeDate (Ye, 12, 31);
- End;
-
- Function FirstDayOfYear (const D : TDateTime) : TDateTime;
- var Ye, Mo, Da : Word;
- Begin
- DecodeDate (D, Ye, Mo, Da);
- Result := EncodeDate (Ye, 1, 1);
- End;
-
- { This algorithm comes from http://www.tondering.dk/claus/calendar.html: }
- { " This algorithm is based in part on the algorithm of Oudin (1940) as }
- { quoted in "Explanatory Supplement to the Astronomical Almanac", }
- { P. Kenneth Seidelmann, editor. }
- { People who want to dig into the workings of this algorithm, may be }
- { interested to know that }
- { G is the Golden Number-1 }
- { H is 23-Epact (modulo 30) }
- { I is the number of days from 21 March to the Paschal full moon }
- { J is the weekday for the Paschal full moon (0=Sunday, 1=Monday,etc.) }
- { L is the number of days from 21 March to the Sunday on or before }
- { the Paschal full moon (a number between -6 and 28) " }
- Function EasterSunday (const Year : Word) : TDateTime;
- var C, I, J, H, G, L : Integer;
- D, M : Word;
- Begin
- G := Year mod 19;
- C := Year div 100;
- H := (C - C div 4 - (8 * C + 13) div 25 + 19 * G + 15) mod 30;
- I := H - (H div 28) * (1 - (H div 28) * (29 div (H + 1)) * ((21 - G) div 11));
- J := (Year + Year div 4 + I + 2 - C + C div 4) mod 7;
- L := I - J;
- M := 3 + (L + 40) div 44;
- D := L + 28 - 31 * (M div 4);
- Result := EncodeDate (Year, M, D);
- End;
-
- Function GoodFriday (const Year : Word) : TDateTime;
- Begin
- Result := EasterSunday (Year) - 2 * OneDay;
- End;
-
- Function AddMilliseconds (const D : TDateTime; const N : Int64) : TDateTime;
- Begin
- Result := D + OneMillisecond * N;
- End;
-
- Function AddSeconds (const D : TDateTime; const N : Int64) : TDateTime;
- Begin
- Result := D + OneSecond * N;
- End;
-
- Function AddMinutes (const D : TDateTime; const N : Integer) : TDateTime;
- Begin
- Result := D + OneMinute * N;
- End;
-
- Function AddHours (const D : TDateTime; const N : Integer) : TDateTime;
- Begin
- Result := D + OneHour * N;
- End;
-
- Function AddDays (const D : TDateTime; const N : Integer) : TDateTime;
- Begin
- Result := D + N;
- End;
-
- Function AddWeeks (const D : TDateTime; const N : Integer) : TDateTime;
- Begin
- Result := D + N * 7 * OneDay;
- End;
-
- Function AddMonths (const D : TDateTime; const N : Integer) : TDateTime;
- var Ye, Mo, Da : Word;
- IMo : Integer;
- Begin
- DecodeDate (D, Ye, Mo, Da);
- Inc (Ye, N div 12);
- IMo := Mo;
- Inc (IMo, N mod 12);
- if IMo > 12 then
- begin
- Dec (IMo, 12);
- Inc (Ye);
- end else
- if IMo < 1 then
- begin
- Inc (IMo, 12);
- Dec (Ye);
- end;
- Mo := IMo;
- Da := MinI (Da, DaysInMonth (Ye, Mo));
- Result := EncodeDate (Ye, Mo, Da) + Frac (D);
- End;
-
- Function AddYears (const D : TDateTime; const N : Integer) : TDateTime;
- var Ye, Mo, Da : Word;
- Begin
- DecodeDate (D, Ye, Mo, Da);
- Inc (Ye, N);
- Da := MinI (Da, DaysInMonth (Ye, Mo));
- Result := EncodeDate (Ye, Mo, Da);
- End;
-
-
-
-
- { }
- { Counting }
- { }
- const
- DaysInNonLeapMonth : Array [1..12] of Integer = (
- 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
- CumDaysInNonLeapMonth : Array [1..12] of Integer = (
- 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334);
-
- Function DayOfYear (const Ye, Mo, Da : Word) : Integer; overload;
- Begin
- Result := CumDaysInNonLeapMonth [Mo] + Da;
- if (Mo > 2) and IsLeapYear (Ye) then
- Inc (Result);
- End;
-
- Function DayOfYear (const D : TDateTime) : Integer; overload;
- var Ye, Mo, Da : Word;
- Begin
- DecodeDate (D, Ye, Mo, Da);
- Result := DayOfYear (Ye, Mo, Da);
- End;
-
- Function DaysInMonth (const Ye, Mo : Word) : Integer;
- Begin
- Result := DaysInNonLeapMonth [Mo];
- if (Mo = 2) and IsLeapYear (Ye) then
- Inc (Result);
- End;
-
- Function DaysInMonth (const D : TDateTime) : Integer;
- var Ye, Mo, Da : Word;
- Begin
- DecodeDate (D, Ye, Mo, Da);
- Result := DaysInMonth (Ye, Mo);
- End;
-
- Function DaysInYear (const Ye : Word) : Integer;
- Begin
- if IsLeapYear (Ye) then
- Result := 366 else
- Result := 365;
- End;
-
- Function DaysInYear (const D : TDateTime) : Integer;
- var Ye, Mo, Da : Word;
- Begin
- DecodeDate (D, Ye, Mo, Da);
- Result := DaysInYear (Ye);
- End;
-
- Function WeekNumber (const D : TDateTime) : Integer;
- Begin
- Result := (DiffDays (FirstDayOfYear (D), D) div 7) + 1;
- End;
-
- { ISO Week functions courtesy of Martin Boonstra (m.boonstra@imn.nl) }
- Function ISOFirstWeekOfYear (const Ye : Integer) : TDateTime;
- const WeekStartOffset : Array [1..7] of Integer = (1, 0, -1, -2, -3, 3, 2);
- // Weekday Start of ISO week 1 is
- // 1 Su 02-01-Year
- // 2 Mo 01-01-Year
- // 3 Tu 31-12-(Year-1)
- // 4 We 30-12-(Year-1)
- // 5 Th 29-12-(Year-1)
- // 6 Fr 04-01-Year
- // 7 Sa 03-01-Year
- Begin
- // Adjust with an offset from 01-01-Ye
- Result := EncodeDate (Ye, 1, 1);
- Result := AddDays (Result, WeekStartOffset [DayOfWeek (Result)]);
- End;
-
- Procedure ISOWeekNumber (const D : TDateTime; var WeekNumber, WeekYear : Word);
- var Ye : Word;
- ISOFirstWeekOfPrevYear,
- ISOFirstWeekOfCurrYear,
- ISOFirstWeekOfNextYear : TDateTime;
- Begin
- { 3 cases: }
- { 1: D < ISOFirstWeekOfCurrYear }
- { D lies in week 52/53 of previous year }
- { 2: ISOFirstWeekOfCurrYear <= D < ISOFirstWeekOfNextYear }
- { D lies in week N (1..52/53) of this year }
- { 3: D >= ISOFirstWeekOfNextYear }
- { D lies in week 1 of next year }
- Ye := Year (D);
- ISOFirstWeekOfCurrYear := ISOFirstWeekOfYear (Ye);
- if D >= ISOFirstWeekOfCurrYear then
- begin
- ISOFirstWeekOfNextYear := ISOFirstWeekOfYear (Ye + 1);
- if (D < ISOFirstWeekOfNextYear) then
- begin // case 2
- WeekNumber := DiffDays (ISOFirstWeekOfCurrYear, D) div 7 + 1;
- WeekYear := Ye;
- end else
- begin // case 3
- WeekNumber := 1;
- WeekYear := Ye + 1;
- end;
- end else
- begin // case 1
- ISOFirstWeekOfPrevYear := ISOFirstWeekOfYear (Ye - 1);
- WeekNumber := DiffDays (ISOFirstWeekOfPrevYear, D) div 7 + 1;
- WeekYear := Ye - 1;
- end;
- End;
-
- Function DateTimeAsISO8601String (const D : TDateTime) : String;
- Begin
- Result := FormatDateTime ('yyyymmdd', D) + 'T' + FormatDateTime ('hh:nn:ss', D);
- End;
-
- Function ISO8601StringAsDateTime (const D : String) : TDateTime;
- var Date, Time : String;
- Ye, Mo, Da : Integer;
- Begin
- Split (UpperCase (D), 'T', Date, Time);
- Ye := StrToInt (CopyLeft (Date, 4));
- Mo := StrToInt (CopyRange (Date, 5, 6));
- Da := StrToInt (CopyRange (Date, 7, 8));
- Result := EncodeDate (Ye, Mo, Da) + StrToTime (Time);
- End;
-
-
-
- { }
- { Difference }
- { }
- Function DiffMilliseconds (const D1, D2 : TDateTime) : Int64;
- Begin
- Result := Trunc ((D2 - D1) / OneMillisecond);
- End;
-
- Function DiffSeconds (const D1, D2 : TDateTime) : Integer;
- Begin
- Result := Trunc ((D2 - D1) / OneSecond);
- End;
-
- Function DiffMinutes (const D1, D2 : TDateTime) : Integer;
- Begin
- Result := Trunc ((D2 - D1) / OneMinute);
- End;
-
- Function DiffHours (const D1, D2 : TDateTime) : Integer;
- Begin
- Result := Trunc ((D2 - D1) / OneHour);
- End;
-
- Function DiffDays (const D1, D2 : TDateTime) : Integer;
- Begin
- Result := Trunc (D2 - D1);
- End;
-
- Function DiffWeeks (const D1, D2 : TDateTime) : Integer;
- Begin
- Result := Trunc (D2 - D1) div 7;
- End;
-
- Function DiffMonths (const D1, D2 : TDateTime) : Integer;
- var Ye1, Mo1, Da1 : Word;
- Ye2, Mo2, Da2 : Word;
- ModMonth1,
- ModMonth2 : TDateTime;
- Begin
- DecodeDate (D1, Ye1, Mo1, Da1);
- DecodeDate (D2, Ye2, Mo2, Da2);
- Result := (Ye2 - Ye1) * 12 + (Mo2 - Mo1);
- ModMonth1 := Da1 + Frac (D1);
- ModMonth2 := Da2 + Frac (D2);
- if (D2 > D1) and (ModMonth2 < ModMonth1) then
- Dec (Result);
- if (D2 < D1) and (ModMonth2 > ModMonth1) then
- Inc (Result);
- End;
-
- Function DiffYears (const D1, D2 : TDateTime) : Integer;
- var Ye1, Mo1, Da1 : Word;
- Ye2, Mo2, Da2 : Word;
- ModYear1,
- ModYear2 : TDateTime;
- Begin
- DecodeDate (D1, Ye1, Mo1, Da1);
- DecodeDate (D2, Ye2, Mo2, Da2);
- Result := Ye2 - Ye1;
- ModYear1 := Mo1 * 31 + Da1 + Frac (Da1);
- ModYear2 := Mo2 * 31 + Da2 + Frac (Da2);
- if (D2 > D1) and (ModYear2 < ModYear1) then
- Dec (Result);
- if (D2 < D1) and (ModYear2 > ModYear1) then
- Inc (Result);
- End;
-
-
-
- { }
- { Conversions }
- { }
- Function DateTimeToANSI (const D : TDateTime) : Integer;
- var Ye, Mo, Da : Word;
- Begin
- DecodeDate (D, Ye, Mo, Da);
- Result := Ye * 1000 + DayOfYear (Ye, Mo, Da);
- End;
-
- Function ANSIToDateTime (const Julian : Integer) : TDateTime;
- var DDD, M, Y : Integer;
- I, C, J : Integer;
- Begin
- DDD := Julian mod 1000;
- if DDD = 0 then
- raise EDateTime.Create ('Invalid ANSI date format');
-
- Y := Julian div 1000;
- M := 0;
- C := 0;
- For I := 1 to 12 do
- begin
- J := DaysInNonLeapMonth [I];
- if (I = 2) and IsLeapYear (Y) then
- Inc (J);
- Inc (C, J);
- if C >= DDD then
- begin
- M := I;
- break;
- end;
- end;
- if M = 0 then // DDD > end of year
- raise EDateTime.Create ('Invalid ANSI date format');
-
- Result := EncodeDate (Y, M, DDD - C + J);
- End;
-
- Function DateTimeToISOInteger (const D : TDateTime) : Integer;
- var Ye, Mo, Da : Word;
- Begin
- DecodeDate (D, Ye, Mo, Da);
- Result := Ye * 10000 + Mo * 100 + Da;
- End;
-
- Function DateTimeToISO (const D : TDateTime) : String;
- var Ye, Mo, Da : Word;
- Begin
- DecodeDate (D, Ye, Mo, Da);
- Result := IntToStr (Ye) + '-' +
- PadLeft (IntToStr (Mo), '0', 2) + '-' +
- PadLeft (IntToStr (Da), '0', 2);
- End;
-
- Function ISOIntegerToDateTime (const ISOInteger : Integer) : TDateTime;
- var Ye, Mo, Da : Word;
- Begin
- Ye := ISOInteger div 10000;
- Mo := (ISOInteger mod 10000) div 100;
- if (Mo < 1) or (Mo > 12) then
- raise EDateTime.Create ('Invalid ISO Integer date format');
- Da := ISOInteger mod 100;
- if (Da < 1) or (Da > DaysInMonth (Ye, Mo)) then
- raise EDateTime.Create ('Invalid ISO Integer date format');
- Result := EncodeDate (Ye, Mo, Da);
- End;
-
- Function DateTimeAsElapsedTime (const D : TDateTime) : String;
- Begin
- Result := IntToStr (Trunc (D) * 24 + Hour (D)) + ':' +
- PadLeft (IntToStr (Minute (D)), '0', 2) + ':' +
- PadLeft (IntToStr (Second (D)), '0', 2);
- End;
-
-
-
- { }
- { Time Zone }
- { }
-
- { Returns the GMT bias (in minutes) from the operating system's regional }
- { settings. }
- Function GMTBias : Integer;
- var TZI : TTimeZoneInformation;
- Begin
- if GetTimeZoneInformation (TZI) = TIME_ZONE_ID_DAYLIGHT then
- Result := TZI.DaylightBias else
- Result := 0;
- Result := Result + TZI.Bias;
- End;
-
- { Converts GMT Time to Local Time }
- Function GMTTimeToLocalTime (const D : TDateTime) : TDateTime;
- Begin
- Result := D - GMTBias / (24 * 60);
- End;
-
- { Converts Local Time to GMT Time }
- Function LocalTimeToGMTTime (const D : TDateTime) : TDateTime;
- Begin
- Result := D + GMTBias / (24 * 60);
- End;
-
- { Quickie: Hard coded with a radix of year 2000. }
- Function TwoDigitYearToYear (const Y : Integer) : Integer;
- Begin
- if Y < 50 then
- Result := 2000 + Y else
- Result := 1900 + Y;
- End;
-
-
-
- { }
- { RFC DateTime }
- { }
- const
- RFC850DayNames : Array [1..7] of String = (
- 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday');
- RFC1123DayNames : Array [1..7] of String = (
- 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');
- RFCMonthNames : Array [1..12] of String = (
- 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
-
- Function RFC850DayOfWeek (const S : String) : Integer;
- var I : Integer;
- Begin
- For I := 1 to 7 do
- if IsEqualNoCase (RFC850DayNames [I], S) then
- begin
- Result := I;
- exit;
- end;
- Result := -1;
- End;
-
- Function RFC1123DayOfWeek (const S : String) : Integer;
- var I : Integer;
- Begin
- For I := 1 to 7 do
- if IsEqualNoCase (RFC1123DayNames [I], S) then
- begin
- Result := I;
- exit;
- end;
- Result := -1;
- End;
-
- Function RFCMonth (const S : String) : Integer;
- var I : Integer;
- Begin
- For I := 1 to 12 do
- if IsEqualNoCase (RFCMonthNames [I], S) then
- begin
- Result := I;
- exit;
- end;
- Result := -1;
- End;
-
- Function GMTTimeToRFC1123Time (const D : TDateTime; const IncludeSeconds : Boolean) : String;
- var Ho, Mi, Se, Ms : Word;
- Begin
- DecodeTime (D, Ho, Mi, Se, Ms);
- Result := PadLeft (IntToStr (Ho), '0', 2) + ':' +
- PadLeft (IntToStr (Mi), '0', 2);
- if IncludeSeconds then
- Result := Result + ':' + PadLeft (IntToStr (Se), '0', 2);
- Result := Result + ' GMT';
- End;
-
- Function GMTDateTimeToRFC1123DateTime (const D : TDateTime; const IncludeDayOfWeek : Boolean) : String;
- var Ye, Mo, Da : Word;
- Begin
- DecodeDate (D, Ye, Mo, Da);
- if IncludeDayOfWeek then
- Result := RFC1123DayNames [DayOfWeek (D)] + ', ' else
- Result := '';
- Result := Result +
- PadLeft (IntToStr (Da), '0', 2) + ' ' +
- RFCMonthNames [Mo] + ' ' +
- IntToStr (Ye) + ' ' +
- GMTTimeToRFC1123Time (D, True);
- End;
-
- Function DateTimeToRFCDateTime (const D : TDateTime) : String;
- Begin
- Result := GMTDateTimeToRFC1123DateTime (LocalTimeToGMTTime (D), True);
- End;
-
- Function RFCTimeZoneToGMTBias (const Zone : String) : Integer;
- type
- TZoneBias = record
- Zone : String;
- Bias : Integer;
- end;
-
- const
- SPACE = cs_WhiteSpace;
- TimeZones = 35;
- ZoneBias : Array [1..TimeZones] of TZoneBias =
- ((Zone:'GMT'; Bias:0), (Zone:'UT'; Bias:0),
- (Zone:'EST'; Bias:-5*60), (Zone:'EDT'; Bias:-4*60),
- (Zone:'CST'; Bias:-6*60), (Zone:'CDT'; Bias:-5*60),
- (Zone:'MST'; Bias:-7*60), (Zone:'MDT'; Bias:-6*60),
- (Zone:'PST'; Bias:-8*60), (Zone:'PDT'; Bias:-7*60),
- (Zone:'Z'; Bias:0), (Zone:'A'; Bias:-1*60),
- (Zone:'B'; Bias:-2*60), (Zone:'C'; Bias:-3*60),
- (Zone:'D'; Bias:-4*60), (Zone:'E'; Bias:-5*60),
- (Zone:'F'; Bias:-6*60), (Zone:'G'; Bias:-7*60),
- (Zone:'H'; Bias:-8*60), (Zone:'I'; Bias:-9*60),
- (Zone:'K'; Bias:-10*60), (Zone:'L'; Bias:-11*60),
- (Zone:'M'; Bias:-12*60), (Zone:'N'; Bias:1*60),
- (Zone:'O'; Bias:2*60), (Zone:'P'; Bias:3*60),
- (Zone:'Q'; Bias:4*60), (Zone:'R'; Bias:3*60),
- (Zone:'S'; Bias:6*60), (Zone:'T'; Bias:3*60),
- (Zone:'U'; Bias:8*60), (Zone:'V'; Bias:3*60),
- (Zone:'W'; Bias:10*60), (Zone:'X'; Bias:3*60),
- (Zone:'Y'; Bias:12*60));
-
- var
- S : String;
- I : Integer;
-
- Begin
- if Zone [1] in ['+', '-'] then // +hhmm format
- begin
- S := Trim (Zone, SPACE);
- Result := MaxI (-23, MinI (23, StrToIntDef (Copy (S, 2, 2), 0))) * 60;
- S := CopyFrom (S, 4);
- if S <> '' then
- Result := Result + MinI (59, MaxI (0, StrToIntDef (S, 0)));
- if Zone [1] = '-' then
- Result := -Result;
- end else
- begin // named format
- S := Trim (Zone, SPACE);
- For I := 1 to TimeZones do
- if IsEqualNoCase (ZoneBias [I].Zone, S) then
- begin
- Result := ZoneBias [I].Bias;
- exit;
- end;
- Result := 0;
- end;
- End;
-
- Function RFCTimeToGMTTime (const S : String) : TDateTime;
- const
- SPACE = cs_WhiteSpace;
-
- var
- I : Integer;
- T : String;
- HH, MM, SS : Integer;
- U : StringArray;
-
- Begin
- U := nil;
- Result := 0.0;
- T := Trim (S, SPACE);
- if T = '' then
- exit;
-
- // Get Zone bias
- I := Pos (SPACE, T, [foReverse]);
- if I > 0 then
- begin
- Result := Int (RFCTimeZoneToGMTBias (CopyFrom (T, I + 1))) / 1440.0;
- T := Trim (CopyLeft (T, I - 1), SPACE);
- end;
-
- // Get time
- U := Split (T, ':');
- if (Length (U) = 1) and (Length (U [0]) = 4) then
- begin // old hhmm format
- HH := StrToIntDef (Copy (U [0], 1, 2), 0);
- MM := StrToIntDef (Copy (U [0], 3, 2), 0);
- SS := 0;
- end else
- if (Length (U) >= 2) or (Length (U) <= 3) then // hh:mm[:ss] format (RFC1123)
- begin
- HH := StrToIntDef (Trim (U [0], SPACE), 0);
- MM := StrToIntDef (Trim (U [1], SPACE), 0);
- if Length (U) = 3 then
- SS := StrToIntDef (Trim (U [2], SPACE), 0) else
- SS := 0;
- end else
- exit;
-
- Result := Result + EncodeTime (MaxI (0, MinI (23, HH)), MaxI (0, MinI (59, MM)),
- MaxI (0, MinI (59, SS)), 0);
- End;
-
- Function RFCDateTimeToGMTDateTime (const S : String) : TDateTime;
- const
- SPACE = cs_WhiteSpace;
-
- var
- T, U : String;
- I : Integer;
- D, M, Y, DOW : Integer;
- V, W : StringArray;
-
- Begin
- Result := 0.0;
-
- W := nil;
- T := Trim (S, SPACE);
-
- // Extract Day of week
- I := Pos (SPACE + [','], T);
- if I > 0 then
- begin
- U := CopyLeft (T, I - 1);
- DOW := RFC850DayOfWeek (U);
- if DOW = -1 then
- DOW := RFC1123DayOfWeek (U);
- if DOW <> -1 then
- T := Trim (CopyFrom (S, I + 1), SPACE);
- end;
-
- V := Split (T, SPACE);
- if Length (V) < 3 then
- exit;
-
- if Pos ('-', V [0]) > 0 then // RFC850 date, eg "Sunday, 06-Nov-94 08:49:37 GMT"
- begin
- W := Split (V [0], '-');
- if Length (W) <> 3 then
- exit;
- M := RFCMonth (W [1]);
- if M = -1 then
- exit;
- D := StrToIntDef (W [0], 0);
- Y := StrToIntDef (W [2], 0);
- if Y < 100 then
- Y := TwoDigitYearToYear (Y);
- Result := EncodeDate (Y, M, D) + RFCTimeToGMTTime (V [1] + V [2]);
- exit;
- end;
-
- M := RFCMonth (V [1]);
- if M >= 1 then // RFC822 date, eg Sun, 06 Nov 1994 08:49:37 GMT
- begin
- D := StrToIntDef (V [0], 0);
- Y := StrToIntDef (V [2], 0);
- Result := EncodeDate (Y, M, D);
- if Length (V) = 4 then
- Result := Result + RFCTimeToGMTTime (V [3]) else
- if Length (V) >= 5 then
- Result := Result + RFCTimeToGMTTime (V [3] + ' ' + V [4]);
- exit;
- end;
-
- M := RFCMonth (V [0]);
- if M >= 1 then // ANSI C asctime() format, eg "Sun Nov 6 08:49:37 1994"
- begin
- D := StrToIntDef (V [1], 0);
- Y := StrToIntDef (V [3], 0);
- Result := EncodeDate (Y, M, D) + RFCTimeToGMTTime (V [2]);
- end;
- End;
-
- Function RFCDateTimeToDateTime (const S : String) : TDateTime;
- Begin
- Result := GMTTimeToLocalTime (RFCDateTimeToGMTDateTime (S));
- End;
-
- Function NowAsRFCDateTime : String;
- Begin
- Result := DateTimeToRFCDateTime (Now);
- End;
-
-
-
- { }
- { High-precision timing }
- { }
- var
- HighPrecisionTimerInit : Boolean = False;
- HighPrecisionMilliFactor : Int64; // millisecond factor
- HighPrecisionMicroFactor : Int64; // microsecond factor
-
- Function CPUClockFrequency : Int64;
- Begin
- if not QueryPerformanceFrequency (Result) then
- raise EDateTime.Create ('High resolution timer not available');
- End;
-
- Procedure InitHighPrecisionTimer;
- Begin
- HighPrecisionMilliFactor := CPUClockFrequency;
- HighPrecisionMilliFactor := HighPrecisionMilliFactor div 1000;
- HighPrecisionMicroFactor := CPUClockFrequency;
- HighPrecisionMicroFactor := HighPrecisionMicroFactor div 1000000;
- HighPrecisionTimerInit := True;
- End;
-
- Function StartTimer : Int64;
- Begin
- if not HighPrecisionTimerInit then
- InitHighPrecisionTimer;
- QueryPerformanceCounter (Result);
- End;
-
- Function MillisecondsElapsed (const Timer : Int64; const TimerRunning : Boolean = True) : Integer;
- var I : Int64;
- Begin
- if not HighPrecisionTimerInit then
- InitHighPrecisionTimer;
- if not TimerRunning then
- Result := Timer div HighPrecisionMilliFactor else
- begin
- QueryPerformanceCounter (I);
- {$IFDEF DELPHI5}
- {$Q-}
- Result := (I - Timer) div HighPrecisionMilliFactor;
- {$ELSE}
- Result := Int64 (I - Timer) div HighPrecisionMilliFactor;
- {$ENDIF}
- end;
- End;
-
- Function MicrosecondsElapsed (const Timer : Int64; const TimerRunning : Boolean = True) : Integer;
- var I : Int64;
- Begin
- if not HighPrecisionTimerInit then
- InitHighPrecisionTimer;
- if not TimerRunning then
- Result := Timer div HighPrecisionMicroFactor else
- begin
- QueryPerformanceCounter (I);
- {$IFDEF DELPHI5}
- {$Q-}
- Result := (I - Timer) div HighPrecisionMicroFactor;
- {$ELSE}
- Result := Int64 (I - Timer) div HighPrecisionMicroFactor;
- {$ENDIF}
- end;
- End;
-
- Procedure StopTimer (var Timer : Int64);
- var I : Int64;
- Begin
- QueryPerformanceCounter (I);
- {$IFDEF DELPHI5}
- {$Q-}
- Timer := I - Timer;
- {$ELSE}
- Timer := Int64 (I - Timer);
- {$ENDIF}
- End;
-
- Procedure ResumeTimer (var StoppedTimer : Int64);
- Begin
- StoppedTimer := Int64 (StartTimer - StoppedTimer);
- End;
-
- Function StoppedTimer : Int64;
- Begin
- if not HighPrecisionTimerInit then
- InitHighPrecisionTimer;
- Result := 0;
- End;
-
- Function ElapsedTimer (const Milliseconds : Integer) : THPTimer;
- var I : Int64;
- Begin
- if not HighPrecisionTimerInit then
- InitHighPrecisionTimer;
- QueryPerformanceCounter (I);
- {$IFDEF DELPHI5}
- {$Q-}
- Result := I - (Milliseconds * HighPrecisionMilliFactor);
- {$ELSE}
- Result := Int64 (I - (Milliseconds * HighPrecisionMilliFactor));
- {$ENDIF}
- End;
-
- Procedure DelayMicroSeconds (const MicroSeconds : Integer);
- var I, J, F : Int64;
- Begin
- if MicroSeconds <= 0 then
- exit;
- if not HighPrecisionTimerInit then
- InitHighPrecisionTimer;
- if not QueryPerformanceCounter (I) then
- exit;
- {$IFDEF DELPHI5}
- {$Q-}
- F := MicroSeconds * HighPrecisionMicroFactor;
- Repeat
- QueryPerformanceCounter (J);
- J := J - I;
- Until J >= F;
- {$ELSE}
- F := Int64 (MicroSeconds * HighPrecisionMicroFactor);
- Repeat
- QueryPerformanceCounter (J);
- Until Int64 (J - I) >= F;
- {$ENDIF}
- End;
-
-
-
- { }
- { Self testing code }
- { }
- Procedure SelfTest;
- var A, B : TDateTime;
- Ye, Mo, Da, Ho, Mi, Se, Ms : Word;
- Ye2, Mo2, Da2, Ho2, Mi2, Se2, Ms2 : Word;
- S : String;
- Begin
- Ho := 7;
- Mi := 10;
- Da := 8;
- Ms := 3;
- For Ye := 1999 to 2001 do
- For Mo := 1 to 12 do
- For Se := 0 to 59 do
- begin
- A := EncodeDateTime (Ye, Mo, Da, Ho, Mi, Se, Ms);
- DecodeDateTime (A, Ye2, Mo2, Da2, Ho2, Mi2, Se2, Ms2);
- Assert (Ye = Ye2, 'DecodeDate');
- Assert (Mo = Mo2, 'DecodeDate');
- Assert (Da = Da2, 'DecodeDate');
- Assert (Ho = Ho2, 'DecodeDate');
- Assert (Mi = Mi2, 'DecodeDate');
- Assert (Se = Se2, 'DecodeDate');
- Assert (Ms = Ms2, 'DecodeDate');
- Assert (Year (A) = Ye, 'Year');
- Assert (Month (A) = Mo, 'Month');
- Assert (Day (A) = Da, 'Day');
- Assert (Hour (A) = Ho, 'Hour');
- Assert (Minute (A) = Mi, 'Minute');
- Assert (Second (A) = Se, 'Second');
- Assert (Millisecond (A) = Ms, 'Millisecond');
- end;
- A := EncodeDateTime (2002, 05, 31, 07, 04, 01, 02);
- Assert (IsEqual (A, 2002, 05, 31), 'IsEqual');
- Assert (IsEqual (A, 07, 04, 01, 02), 'IsEqual');
- Assert (IsFriday (A), 'IsFriday');
- Assert (not IsMonday (A), 'IsMonday');
- A := AddWeeks (A, 2);
- Assert (IsEqual (A, 2002, 06, 14), 'AddWeeks');
- A := AddHours (A, 2);
- Assert (IsEqual (A, 09, 04, 01, 02), 'AddHours');
- A := EncodeDateTime (2004, 03, 01, 0, 0, 0, 0);
- Assert (DayOfYear (A) = 61, 'DayOfYear');
- Assert (DaysInMonth (2004, 02) = 29, 'DaysInMonth');
- Assert (DaysInMonth (2005, 02) = 28, 'DaysInMonth');
- Assert (DaysInMonth (2001, 01) = 31, 'DaysInMonth');
- Assert (DaysInYear (2000) = 366, 'DaysInYear');
- Assert (DaysInYear (2004) = 366, 'DaysInYear');
- Assert (DaysInYear (2006) = 365, 'DaysInYear');
- A := EncodeDateTime (2001, 09, 02, 12, 11, 10, 0);
- S := GMTDateTimeToRFC1123DateTime (A, True);
- Assert (S = 'Sun, 02 Sep 2001 12:11:10 GMT', 'GMTDateTimeToRFC1123DateTime');
- B := RFCDateTimeToGMTDateTime (S);
- Assert (IsEqual (A, B), 'RFCDateTimeToGMTDateTime');
- End;
-
-
-
- end.
-
-