/[projects]/dao/DelphiScanner/Components/tpsystools_4.04/source/StDate.pas
ViewVC logotype

Contents of /dao/DelphiScanner/Components/tpsystools_4.04/source/StDate.pas

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2671 - (show annotations) (download)
Tue Aug 25 18:15:15 2015 UTC (8 years, 9 months ago) by torben
File size: 26973 byte(s)
Added tpsystools component
1 // Upgraded to Delphi 2009: Sebastian Zierer
2
3 (* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1
5 *
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
10 *
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
15 *
16 * The Original Code is TurboPower SysTools
17 *
18 * The Initial Developer of the Original Code is
19 * TurboPower Software
20 *
21 * Portions created by the Initial Developer are Copyright (C) 1996-2002
22 * the Initial Developer. All Rights Reserved.
23 *
24 * Contributor(s):
25 *
26 * ***** END LICENSE BLOCK ***** *)
27
28 {*********************************************************}
29 {* SysTools: StDate.pas 4.04 *}
30 {*********************************************************}
31 {* SysTools: Date and time manipulation *}
32 {*********************************************************}
33
34 {$I StDefine.inc}
35
36 {For BCB 3.0 package support.}
37 {$IFDEF VER110}
38 {$ObjExportAll On}
39 {$ENDIF}
40
41 unit StDate;
42
43 interface
44
45 uses
46 Windows, SysUtils;
47
48 type
49 TStDate = LongInt;
50 {In STDATE, dates are stored in long integer format as the number of days
51 since January 1, 1600}
52
53 TDateArray = array[0..(MaxLongInt div SizeOf(TStDate))-1] of TStDate;
54 {Type for StDate open array}
55
56 TStDayType = (Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday);
57 {An enumerated type used when representing a day of the week}
58
59 TStBondDateType = (bdtActual, bdt30E360, bdt30360, bdt30360psa);
60 {An enumerated type used for calculating bond date differences}
61
62 TStTime = LongInt;
63 {STDATE handles time in a manner similar to dates, representing a given
64 time of day as the number of seconds since midnight}
65
66 TStDateTimeRec =
67 record
68 {This record type simply combines the two basic date types defined by
69 STDATE, Date and Time}
70 D : TStDate;
71 T : TStTime;
72 end;
73
74 const
75 MinYear = 1600; {Minimum valid year for a date variable}
76 MaxYear = 3999; {Maximum valid year for a date variable}
77 Mindate = $00000000; {Minimum valid date for a date variable - 01/01/1600}
78 Maxdate = $000D6025; {Maximum valid date for a date variable - 12/31/3999}
79 Date1900 : longint = $0001AC05; {Julian date for 01/01/1900}
80 Date1970 : longint = $00020FE4; {Julian date for 01/01/1970}
81 Date1980 : longint = $00021E28; {Julian date for 01/01/1980}
82 Date2000 : longint = $00023AB1; {Julian date for 01/01/2000}
83 Days400Yr : longint = 146097; {days in 400 years}
84 {This value is used to represent an invalid date, such as 12/32/1992}
85 BadDate = LongInt($FFFFFFFF);
86
87 DeltaJD = $00232DA8; {Days between 1/1/-4173 and 1/1/1600}
88
89 MinTime = 0; {Minimum valid time for a time variable - 00:00:00 am}
90 MaxTime = 86399; {Maximum valid time for a time variable - 23:59:59 pm}
91 {This value is used to represent an invalid time of day, such as 12:61:00}
92 BadTime = LongInt($FFFFFFFF);
93 SecondsInDay = 86400; {Number of seconds in a day}
94 SecondsInHour = 3600; {Number of seconds in an hour}
95 SecondsInMinute = 60; {Number of seconds in a minute}
96 HoursInDay = 24; {Number of hours in a day}
97 MinutesInHour = 60; {Number of minutes in an hour}
98 MinutesInDay = 1440; {Number of minutes in a day}
99
100 var
101 DefaultYear : Integer; {default year--used by DateStringToDMY}
102 DefaultMonth : ShortInt; {default month}
103
104 {-------julian date routines---------------}
105
106 function CurrentDate : TStDate;
107 {-returns today's date as a Julian date}
108
109 function ValidDate(Day, Month, Year, Epoch : Integer) : Boolean;
110 {-Verify that day, month, year is a valid date}
111
112 function DMYtoStDate(Day, Month, Year, Epoch : Integer) : TStDate;
113 {-Convert from day, month, year to a Julian date}
114
115 procedure StDateToDMY(Julian : TStDate; var Day, Month, Year : Integer);
116 {-Convert from a Julian date to day, month, year}
117
118 function IncDate(Julian : TStDate; Days, Months, Years : Integer) : TStDate;
119 {-Add (or subtract) the number of days, months, and years to a date}
120
121 function IncDateTrunc(Julian : TStDate; Months, Years : Integer) : TStDate;
122 {-Add (or subtract) the specified number of months and years to a date}
123
124 procedure DateDiff(Date1, Date2 : TStDate;
125 var Days, Months, Years : Integer);
126 {-Return the difference in days, months, and years between two valid Julian
127 dates}
128
129 function BondDateDiff(Date1, Date2 : TStDate; DayBasis : TStBondDateType) : TStDate;
130 {-Return the difference in days between two valid Julian
131 dates using a specific financial basis}
132
133 function WeekOfYear(Julian : TStDate) : Byte;
134 {-Returns the week number of the year given the Julian Date}
135
136 function AstJulianDate(Julian : TStDate) : Double;
137 {-Returns the Astronomical Julian Date from a TStDate}
138
139 function AstJulianDatetoStDate(AstJulian : Double; Truncate : Boolean) : TStDate;
140 {-Returns a TStDate from an Astronomical Julian Date.
141 Truncate TRUE Converts to appropriate 0 hours then truncates
142 FALSE Converts to appropriate 0 hours, then rounds to
143 nearest;}
144
145 function AstJulianDatePrim(Year, Month, Date : Integer; UT : TStTime) : Double;
146 {-Returns an Astronomical Julian Date for any year, even those outside
147 MinYear..MaxYear}
148
149 function DayOfWeek(Julian : TStDate) : TStDayType;
150 {-Return the day of the week for a Julian date}
151
152 function DayOfWeekDMY(Day, Month, Year, Epoch : Integer) : TStDayType;
153 {-Return the day of the week for the day, month, year}
154
155 function IsLeapYear(Year : Integer) : Boolean;
156 {-Return True if Year is a leap year}
157
158 function DaysInMonth(Month : Integer; Year, Epoch : Integer) : Integer;
159 {-Return the number of days in the specified month of a given year}
160
161 function ResolveEpoch(Year, Epoch : Integer) : Integer;
162 {-Convert 2 digit year to 4 digit year according to Epoch}
163
164
165 {-------time routines---------------}
166
167 function ValidTime(Hours, Minutes, Seconds : Integer) : Boolean;
168 {-Return True if Hours:Minutes:Seconds is a valid time}
169
170 procedure StTimeToHMS(T : TStTime;
171 var Hours, Minutes, Seconds : Byte);
172 {-Convert a time variable to hours, minutes, seconds}
173
174 function HMStoStTime(Hours, Minutes, Seconds : Byte) : TStTime;
175 {-Convert hours, minutes, seconds to a time variable}
176
177 function CurrentTime : TStTime;
178 {-Return the current time in seconds since midnight}
179
180 procedure TimeDiff(Time1, Time2 : TStTime;
181 var Hours, Minutes, Seconds : Byte);
182 {-Return the difference in hours, minutes, and seconds between two times}
183
184 function IncTime(T : TStTime; Hours, Minutes, Seconds : Byte) : TStTime;
185 {-Add the specified hours, minutes, and seconds to a given time of day}
186
187 function DecTime(T : TStTime; Hours, Minutes, Seconds : Byte) : TStTime;
188 {-Subtract the specified hours, minutes, and seconds from a given time of day}
189
190 function RoundToNearestHour(T : TStTime; Truncate : Boolean) : TStTime;
191 {-Given a time, round it to the nearest hour, or truncate minutes and
192 seconds}
193
194 function RoundToNearestMinute(const T : TStTime; Truncate : Boolean) : TStTime;
195 {-Given a time, round it to the nearest minute, or truncate seconds}
196
197 {-------- routines for DateTimeRec records ---------}
198
199 procedure DateTimeDiff(const DT1 : TStDateTimeRec; var DT2 : TStDateTimeRec; {!!.02}
200 var Days : LongInt; var Secs : LongInt);
201 {-Return the difference in days and seconds between two points in time}
202
203 procedure IncDateTime(const DT1 : TStDateTimeRec; var DT2 : TStDateTimeRec; {!!.02}
204 Days : Integer; Secs : LongInt);
205 {-Increment (or decrement) a date and time by the specified number of days
206 and seconds}
207
208 function DateTimeToStDate(DT : TDateTime) : TStDate;
209 {-Convert Delphi TDateTime to TStDate}
210
211 function DateTimeToStTime(DT : TDateTime) : TStTime;
212 {-Convert Delphi TDateTime to TStTime}
213
214 function StDateToDateTime(D : TStDate) : TDateTime;
215 {-Convert TStDate to TDateTime}
216
217 function StTimeToDateTime(T : TStTime) : TDateTime;
218 {-Convert TStTime to TDateTime}
219
220 function Convert2ByteDate(TwoByteDate : Word) : TStDate;
221 {-Convert an Object Professional two byte date into a SysTools date}
222
223 function Convert4ByteDate(FourByteDate : TStDate) : Word;
224 {-Convert a SysTools date into an Object Professional two byte date}
225
226
227 implementation
228
229 const
230 First2Months = 59; {1600 was a leap year}
231 FirstDayOfWeek = Saturday; {01/01/1600 was a Saturday}
232 DateLen = 40; {maximum length of Picture strings}
233 MaxMonthName = 15;
234 MaxDayName = 15;
235
236
237 //type
238 { DateString = string[DateLen];}
239 // SString = string[255];
240
241 function IsLeapYear(Year : Integer) : Boolean;
242 {-Return True if Year is a leap year}
243 begin
244 Result := (Year mod 4 = 0) and (Year mod 4000 <> 0) and
245 ((Year mod 100 <> 0) or (Year mod 400 = 0));
246 end;
247
248 function IsLastDayofMonth(Day, Month, Year : Integer) : Boolean;
249 {-Return True if date is the last day in month}
250 var
251 Epoch : Integer;
252 begin
253 Epoch := (Year div 100) * 100;
254 if ValidDate(Day + 1, Month, Year, Epoch) then
255 Result := false
256 else
257 Result := true;
258 end;
259
260 function IsLastDayofFeb(Date : TStDate) : Boolean;
261 {-Return True if date is the last day in February}
262 var
263 Day, Month, Year : Integer;
264 begin
265 StDateToDMY(Date, Day, Month, Year);
266 if (Month = 2) and IsLastDayOfMonth(Day, Month, Year) then
267 Result := true
268 else
269 Result := false;
270 end;
271
272 procedure ExchangeLongInts(var I, J : LongInt);
273 register;
274 asm
275 mov ecx, [eax]
276 push ecx
277 mov ecx, [edx]
278 mov [eax], ecx
279 pop ecx
280 mov [edx], ecx
281 end;
282
283 procedure ExchangeStructs(var I, J; Size : Cardinal);
284 register;
285 asm
286 push edi
287 push ebx
288 push ecx
289 shr ecx, 2
290 jz @@LessThanFour
291
292 @@AgainDWords:
293 mov ebx, [eax]
294 mov edi, [edx]
295 mov [edx], ebx
296 mov [eax], edi
297 add eax, 4
298 add edx, 4
299 dec ecx
300 jnz @@AgainDWords
301
302 @@LessThanFour:
303 pop ecx
304 and ecx, $3
305 jz @@Done
306 mov bl, [eax]
307 mov bh, [edx]
308 mov [edx], bl
309 mov [eax], bh
310 inc eax
311 inc edx
312 dec ecx
313 jz @@Done
314
315 mov bl, [eax]
316 mov bh, [edx]
317 mov [edx], bl
318 mov [eax], bh
319 inc eax
320 inc edx
321 dec ecx
322 jz @@Done
323
324 mov bl, [eax]
325 mov bh, [edx]
326 mov [edx], bl
327 mov [eax], bh
328
329 @@Done:
330 pop ebx
331 pop edi
332 end;
333
334
335 function ResolveEpoch(Year, Epoch : Integer) : Integer;
336 {-Convert 2-digit year to 4-digit year according to Epoch}
337 var
338 EpochYear,
339 EpochCent : Integer;
340 begin
341 if Word(Year) < 100 then begin
342 EpochYear := Epoch mod 100;
343 EpochCent := (Epoch div 100) * 100;
344 if (Year < EpochYear) then
345 Inc(Year,EpochCent+100)
346 else
347 Inc(Year,EpochCent);
348 end;
349 Result := Year;
350 end;
351
352 function CurrentDate : TStDate;
353 {-Returns today's date as a julian}
354 var
355 Year, Month, Date : Word;
356 begin
357 DecodeDate(Now,Year,Month,Date);
358 Result := DMYToStDate(Date,Month,Year,0);
359 end;
360
361 function DaysInMonth(Month : integer; Year, Epoch : Integer) : Integer;
362 {-Return the number of days in the specified month of a given year}
363 begin
364 Year := ResolveEpoch(Year, Epoch);
365
366 if (Year < MinYear) OR (Year > MaxYear) then
367 begin
368 Result := 0;
369 Exit;
370 end;
371
372 case Month of
373 1, 3, 5, 7, 8, 10, 12 :
374 Result := 31;
375 4, 6, 9, 11 :
376 Result := 30;
377 2 :
378 Result := 28+Ord(IsLeapYear(Year));
379 else
380 Result := 0;
381 end;
382 end;
383
384 function ValidDate(Day, Month, Year, Epoch : Integer) : Boolean;
385 {-Verify that day, month, year is a valid date}
386 begin
387 Year := ResolveEpoch(Year, Epoch);
388
389 if (Day < 1) or (Year < MinYear) or (Year > MaxYear) then
390 Result := False
391 else case Month of
392 1..12 :
393 Result := Day <= DaysInMonth(Month, Year, Epoch);
394 else
395 Result := False;
396 end
397 end;
398
399 function DMYtoStDate(Day, Month, Year, Epoch : Integer) : TStDate;
400 {-Convert from day, month, year to a julian date}
401 begin
402 Year := ResolveEpoch(Year, Epoch);
403
404 if not ValidDate(Day, Month, Year, Epoch) then
405 Result := BadDate
406 else if (Year = MinYear) and (Month < 3) then
407 if Month = 1 then
408 Result := Pred(Day)
409 else
410 Result := Day+30
411 else begin
412 if Month > 2 then
413 Dec(Month, 3)
414 else begin
415 Inc(Month, 9);
416 Dec(Year);
417 end;
418 Dec(Year, MinYear);
419 Result :=
420 ((LongInt(Year div 100)*Days400Yr) div 4)+
421 ((LongInt(Year mod 100)*1461) div 4)+
422 (((153*Month)+2) div 5)+Day+First2Months;
423 end;
424 end;
425
426 function WeekOfYear(Julian : TStDate) : Byte;
427 {-Returns the week number of the year given the Julian Date}
428 var
429 Day, Month, Year : Integer;
430 FirstJulian : TStDate;
431 begin
432 if (Julian < MinDate) or (Julian > MaxDate) then
433 begin
434 Result := 0;
435 Exit;
436 end;
437
438 Julian := Julian + 3 - ((6 + Ord(DayOfWeek(Julian))) mod 7);
439 StDateToDMY(Julian,Day,Month,Year);
440 FirstJulian := DMYToStDate(1,1,Year,0);
441 Result := 1 + (Julian - FirstJulian) div 7;
442 end;
443
444 function AstJulianDate(Julian : TStDate) : Double;
445 {-Returns the Astronomical Julian Date from a TStDate}
446 begin
447 {Subtract 0.5d since Astronomical JD starts at noon
448 while TStDate (with implied .0) starts at midnight}
449 Result := Julian - 0.5 + DeltaJD;
450 end;
451
452
453 function AstJulianDatePrim(Year, Month, Date : Integer; UT : TStTime) : Double;
454 var
455 A, B : integer;
456 LY,
457 GC : Boolean;
458
459 begin
460 Result := -MaxLongInt;
461 if (not (Month in [1..12])) or (Date < 1) then
462 Exit
463 else if (Month in [1, 3, 5, 7, 8, 10, 12]) and (Date > 31) then
464 Exit
465 else if (Month in [4, 6, 9, 11]) and (Date > 30) then
466 Exit
467 else if (Month = 2) then begin
468 LY := IsLeapYear(Year);
469 if ((LY) and (Date > 29)) or (not (LY) and (Date > 28)) then
470 Exit;
471 end else if ((UT < 0) or (UT >= SecondsInDay)) then
472 Exit;
473
474 if (Month <= 2) then begin
475 Year := Year - 1;
476 Month := Month + 12;
477 end;
478 A := abs(Year div 100);
479
480 if (Year > 1582) then
481 GC := True
482 else if (Year = 1582) then begin
483 if (Month > 10) then
484 GC := True
485 else if (Month < 10) then
486 GC := False
487 else begin
488 if (Date >= 15) then
489 GC := True
490 else
491 GC := False;
492 end;
493 end else
494 GC := False;
495 if (GC) then
496 B := 2 - A + abs(A div 4)
497 else
498 B := 0;
499
500 Result := Trunc(365.25 * (Year + 4716))
501 + Trunc(30.6001 * (Month + 1))
502 + Date + B - 1524.5
503 + UT / SecondsInDay;
504 end;
505
506
507 function AstJulianDatetoStDate(AstJulian : Double; Truncate : Boolean) : TStDate;
508 {-Returns a TStDate from an Astronomical Julian Date.
509 Truncate TRUE Converts to appropriate 0 hours then truncates
510 FALSE Converts to appropriate 0 hours, then rounds to
511 nearest;}
512 begin
513 {Convert to TStDate, adding 0.5d for implied .0d of TStDate}
514 AstJulian := AstJulian + 0.5 - DeltaJD;
515 if (AstJulian < MinDate) OR (AstJulian > MaxDate) then
516 begin
517 Result := BadDate;
518 Exit;
519 end;
520
521 if Truncate then
522 Result := Trunc(AstJulian)
523 else
524 Result := Trunc(AstJulian + 0.5);
525 end;
526
527 procedure StDateToDMY(Julian : TStDate; var Day, Month, Year : Integer);
528 {-Convert from a julian date to month, day, year}
529 var
530 I, J : LongInt;
531 begin
532 if Julian = BadDate then begin
533 Day := 0;
534 Month := 0;
535 Year := 0;
536 end else if Julian <= First2Months then begin
537 Year := MinYear;
538 if Julian <= 30 then begin
539 Month := 1;
540 Day := Succ(Julian);
541 end else begin
542 Month := 2;
543 Day := Julian-30;
544 end;
545 end else begin
546 I := (4*LongInt(Julian-First2Months))-1;
547
548 J := (4*((I mod Days400Yr) div 4))+3;
549 Year := (100*(I div Days400Yr))+(J div 1461);
550 I := (5*(((J mod 1461)+4) div 4))-3;
551 Day := ((I mod 153)+5) div 5;
552
553 Month := I div 153;
554 if Month < 10 then
555 Inc(Month, 3)
556 else begin
557 Dec(Month, 9);
558 Inc(Year);
559 end;
560 Inc(Year, MinYear);
561 end;
562 end;
563
564 function IncDate(Julian : TStDate; Days, Months, Years : Integer) : TStDate;
565 {-Add (or subtract) the number of months, days, and years to a date.
566 Months and years are added before days. No overflow/underflow
567 checks are made}
568 var
569 Day, Month, Year, Day28Delta : Integer;
570 begin
571 StDateToDMY(Julian, Day, Month, Year);
572 Day28Delta := Day-28;
573 if Day28Delta < 0 then
574 Day28Delta := 0
575 else
576 Day := 28;
577
578 Inc(Year, Years);
579 Inc(Year, Months div 12);
580 Inc(Month, Months mod 12);
581 if Month < 1 then begin
582 Inc(Month, 12);
583 Dec(Year);
584 end
585 else if Month > 12 then begin
586 Dec(Month, 12);
587 Inc(Year);
588 end;
589
590 Julian := DMYtoStDate(Day, Month, Year,0);
591 if Julian <> BadDate then begin
592 Inc(Julian, Days);
593 Inc(Julian, Day28Delta);
594 end;
595 Result := Julian;
596 end;
597
598 function IncDateTrunc(Julian : TStDate; Months, Years : Integer) : TStDate;
599 {-Add (or subtract) the specified number of months and years to a date}
600 var
601 Day, Month, Year : Integer;
602 MaxDay, Day28Delta : Integer;
603 begin
604 StDateToDMY(Julian, Day, Month, Year);
605 Day28Delta := Day-28;
606 if Day28Delta < 0 then
607 Day28Delta := 0
608 else
609 Day := 28;
610
611 Inc(Year, Years);
612 Inc(Year, Months div 12);
613 Inc(Month, Months mod 12);
614 if Month < 1 then begin
615 Inc(Month, 12);
616 Dec(Year);
617 end
618 else if Month > 12 then begin
619 Dec(Month, 12);
620 Inc(Year);
621 end;
622
623 Julian := DMYtoStDate(Day, Month, Year,0);
624 if Julian <> BadDate then begin
625 MaxDay := DaysInMonth(Month, Year,0);
626 if Day+Day28Delta > MaxDay then
627 Inc(Julian, MaxDay-Day)
628 else
629 Inc(Julian, Day28Delta);
630 end;
631 Result := Julian;
632 end;
633
634 procedure DateDiff(Date1, Date2 : TStDate; var Days, Months, Years : Integer);
635 {-Return the difference in days,months,years between two valid julian dates}
636 var
637 Day1, Day2, Month1, Month2, Year1, Year2 : Integer;
638 begin
639 {we want Date2 > Date1}
640 if Date1 > Date2 then
641 ExchangeLongInts(Date1, Date2);
642
643 {convert dates to day,month,year}
644 StDateToDMY(Date1, Day1, Month1, Year1);
645 StDateToDMY(Date2, Day2, Month2, Year2);
646
647 {days first}
648 if (Day1 = DaysInMonth(Month1, Year1, 0)) then begin
649 Day1 := 0;
650 Inc(Month1); {OK if Month1 > 12}
651 end;
652 if (Day2 = DaysInMonth(Month2, Year2, 0)) then begin
653 Day2 := 0;
654 Inc(Month2); {OK if Month2 > 12}
655 end;
656 if (Day2 < Day1) then begin
657 Dec(Month2);
658 if Month2 = 0 then begin
659 Month2 := 12;
660 Dec(Year2);
661 end;
662 Days := Day2 + DaysInMonth(Month2, Year2, 0) - Day1; {!!.02}
663 end else
664 Days := Day2-Day1;
665
666 {now months and years}
667 if Month2 < Month1 then begin
668 Inc(Month2, 12);
669 Dec(Year2);
670 end;
671 Months := Month2-Month1;
672 Years := Year2-Year1;
673 end;
674
675 function BondDateDiff(Date1, Date2 : TStDate; DayBasis : TStBondDateType) : TStDate;
676 {-Return the difference in days between two valid Julian
677 dates using one a specific accrual method}
678 var
679 Day1,
680 Month1,
681 Year1,
682 Day2,
683 Month2,
684 Year2 : Integer;
685 IY : LongInt;
686 begin
687 {we want Date2 > Date1}
688 if Date1 > Date2 then
689 ExchangeLongInts(Date1, Date2);
690
691 if (DayBasis = bdtActual) then
692 Result := Date2-Date1
693 else
694 begin
695 StDateToDMY(Date1, Day1, Month1, Year1);
696 StDateToDMY(Date2, Day2, Month2, Year2);
697
698 if ((DayBasis = bdt30360PSA) and IsLastDayofFeb(Date1)) or (Day1 = 31) then
699 Day1 := 30;
700 if (DayBasis = bdt30E360) then
701 begin
702 if (Day2 = 31) then
703 Day2 := 30
704 end else
705 if (Day2 = 31) and (Day1 >= 30) then
706 Day2 := 30;
707
708 IY := 360 * (Year2 - Year1);
709 Result := IY + 30 * (Month2 - Month1) + (Day2 - Day1);
710 end;
711 end;
712
713 function DayOfWeek(Julian : TStDate) : TStDayType;
714 {-Return the day of the week for the date. Returns TStDayType(7) if Julian =
715 BadDate.}
716 var
717 B : Byte;
718 begin
719 if Julian = BadDate then begin
720 B := 7;
721 Result := TStDayType(B);
722 end else
723 Result := TStDayType( (Julian+Ord(FirstDayOfWeek)) mod 7 );
724 end;
725
726 function DayOfWeekDMY(Day, Month, Year, Epoch : Integer) : TStDayType;
727 {-Return the day of the week for the day, month, year}
728 begin
729 Result := DayOfWeek( DMYtoStDate(Day, Month, Year, Epoch) );
730 end;
731
732 procedure StTimeToHMS(T : TStTime; var Hours, Minutes, Seconds : Byte);
733 {-Convert a Time variable to Hours, Minutes, Seconds}
734 begin
735 if T = BadTime then begin
736 Hours := 0;
737 Minutes := 0;
738 Seconds := 0;
739 end
740 else begin
741 Hours := T div SecondsInHour;
742 Dec(T, LongInt(Hours)*SecondsInHour);
743 Minutes := T div SecondsInMinute;
744 Dec(T, LongInt(Minutes)*SecondsInMinute);
745 Seconds := T;
746 end;
747 end;
748
749 function HMStoStTime(Hours, Minutes, Seconds : Byte) : TStTime;
750 {-Convert Hours, Minutes, Seconds to a Time variable}
751 var
752 T : TStTime;
753 begin
754 Hours := Hours mod HoursInDay;
755 T := (LongInt(Hours)*SecondsInHour)+(LongInt(Minutes)*SecondsInMinute)+Seconds;
756 Result := T mod SecondsInDay;
757 end;
758
759 function ValidTime(Hours, Minutes, Seconds : Integer) : Boolean;
760 {-Return true if Hours:Minutes:Seconds is a valid time}
761 begin
762 if (Hours < 0) or (Hours > 23) or
763 (Minutes < 0) or (Minutes >= 60) or
764 (Seconds < 0) or (Seconds >= 60) then
765 Result := False
766 else
767 Result := True;
768 end;
769
770 function CurrentTime : TStTime;
771 {-Returns current time in seconds since midnight}
772 begin
773 Result := Trunc(SysUtils.Time * SecondsInDay);
774 end;
775
776 procedure TimeDiff(Time1, Time2 : TStTime; var Hours, Minutes, Seconds : Byte);
777 {-Return the difference in hours,minutes,seconds between two times}
778 begin
779 StTimeToHMS(Abs(Time1-Time2), Hours, Minutes, Seconds);
780 end;
781
782 function IncTime(T : TStTime; Hours, Minutes, Seconds : Byte) : TStTime;
783 {-Add the specified hours,minutes,seconds to T and return the result}
784 begin
785 Inc(T, HMStoStTime(Hours, Minutes, Seconds));
786 Result := T mod SecondsInDay;
787 end;
788
789 function DecTime(T : TStTime; Hours, Minutes, Seconds : Byte) : TStTime;
790 {-Subtract the specified hours,minutes,seconds from T and return the result}
791 begin
792 Hours := Hours mod HoursInDay;
793 Dec(T, HMStoStTime(Hours, Minutes, Seconds));
794 if T < 0 then
795 Result := T+SecondsInDay
796 else
797 Result := T;
798 end;
799
800 function RoundToNearestHour(T : TStTime; Truncate : Boolean) : TStTime;
801 {-Round T to the nearest hour, or Truncate minutes and seconds from T}
802 var
803 Hours, Minutes, Seconds : Byte;
804 begin
805 StTimeToHMS(T, Hours, Minutes, Seconds);
806 Seconds := 0;
807 if not Truncate then
808 if Minutes >= (MinutesInHour div 2) then
809 Inc(Hours);
810 Minutes := 0;
811 Result := HMStoStTime(Hours, Minutes, Seconds);
812 end;
813
814 function RoundToNearestMinute(const T : TStTime; Truncate : Boolean) : TStTime;
815 {-Round T to the nearest minute, or Truncate seconds from T}
816 var
817 Hours, Minutes, Seconds : Byte;
818 begin
819 StTimeToHMS(T, Hours, Minutes, Seconds);
820 if not Truncate then
821 if Seconds >= (SecondsInMinute div 2) then
822 Inc(Minutes);
823 Seconds := 0;
824 Result := HMStoStTime(Hours, Minutes, Seconds);
825 end;
826
827
828 procedure DateTimeDiff(const DT1 : TStDateTimeRec; var DT2 : TStDateTimeRec; {!!.02}
829 var Days : LongInt; var Secs : LongInt);
830 {-Return the difference in days and seconds between two points in time}
831 var
832 tDT1, tDT2 : TStDateTimeRec;
833 begin
834 tDT1 := DT1;
835 tDT2 := DT2;
836 {swap if tDT1 later than tDT2}
837 if (tDT1.D > tDT2.D) or ((tDT1.D = tDT2.D) and (tDT1.T > tDT2.T)) then
838 ExchangeStructs(tDT1, tDT2,sizeof(TStDateTimeRec));
839
840 {the difference in days is easy}
841 Days := tDT2.D-tDT1.D;
842
843 {difference in seconds}
844 if tDT2.T < tDT1.T then begin
845 {subtract one day, add 24 hours}
846 Dec(Days);
847 Inc(tDT2.T, SecondsInDay);
848 end;
849 Secs := tDT2.T-tDT1.T;
850 end;
851
852 function DateTimeToStDate(DT : TDateTime) : TStDate;
853 {-Convert Delphi TDateTime to TStDate}
854 var
855 Day, Month, Year : Word;
856 begin
857 DecodeDate(DT, Year, Month, Day);
858 Result := DMYToStDate(Day, Month, Year, 0);
859 end;
860
861 function DateTimeToStTime(DT : TDateTime) : TStTime;
862 {-Convert Delphi TDateTime to TStTime}
863 var
864 Hour, Min, Sec, MSec : Word;
865 begin
866 DecodeTime(DT, Hour, Min, Sec, MSec);
867 Result := HMSToStTime(Hour, Min, Sec);
868 end;
869
870 function StDateToDateTime(D : TStDate) : TDateTime;
871 {-Convert TStDate to TDateTime}
872 var
873 Day, Month, Year : Integer;
874 begin
875 Result := 0;
876 if D <> BadDate then begin
877 StDateToDMY(D, Day, Month, Year);
878 Result := EncodeDate(Year, Month, Day);
879 end;
880 end;
881
882 function StTimeToDateTime(T : TStTime) : TDateTime;
883 {-Convert TStTime to TDateTime}
884 var
885 Hour, Min, Sec : Byte;
886 begin
887 Result := 0;
888 if T <> BadTime then begin
889 StTimeToHMS(T, Hour, Min, Sec);
890 Result := EncodeTime(Hour, Min, Sec, 0);
891 end;
892 end;
893
894 procedure IncDateTime(const DT1 : TStDateTimeRec; var DT2 : TStDateTimeRec; {!!.02}
895 Days : Integer; Secs : LongInt);
896 {-Increment (or decrement) DT1 by the specified number of days and seconds
897 and put the result in DT2}
898 begin
899 DT2 := DT1;
900
901 {date first}
902 Inc(DT2.D, LongInt(Days));
903
904 if Secs < 0 then begin
905 {change the sign}
906 Secs := -Secs;
907
908 {adjust the date}
909 Dec(DT2.D, Secs div SecondsInDay);
910 Secs := Secs mod SecondsInDay;
911
912 if Secs > DT2.T then begin
913 {subtract a day from DT2.D and add a day's worth of seconds to DT2.T}
914 Dec(DT2.D);
915 Inc(DT2.T, SecondsInDay);
916 end;
917
918 {now subtract the seconds}
919 Dec(DT2.T, Secs);
920 end
921 else begin
922 {increment the seconds}
923 Inc(DT2.T, Secs);
924
925 {adjust date if necessary}
926 Inc(DT2.D, DT2.T div SecondsInDay);
927
928 {force time to 0..SecondsInDay-1 range}
929 DT2.T := DT2.T mod SecondsInDay;
930 end;
931 end;
932
933 function Convert2ByteDate(TwoByteDate : Word) : TStDate;
934 begin
935 Result := LongInt(TwoByteDate) + Date1900;
936 end;
937
938 function Convert4ByteDate(FourByteDate : TStDate) : Word;
939 begin
940 Result := Word(FourByteDate - Date1900);
941 end;
942
943 procedure SetDefaultYear;
944 {-Initialize DefaultYear and DefaultMonth}
945 var
946 Month, Day, Year : Word;
947 T : TDateTime;
948 begin
949 T := Now;
950 DecodeDate(T, Year, Month, Day);
951 DefaultYear := Year;
952 DefaultMonth := Month;
953 end;
954
955
956 initialization
957 {initialize DefaultYear and DefaultMonth}
958 SetDefaultYear;
959 end.

  ViewVC Help
Powered by ViewVC 1.1.20