DateTime.ob07 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. (*
  2. BSD 2-Clause License
  3. Copyright (c) 2019-2020, Anton Krotov
  4. All rights reserved.
  5. *)
  6. MODULE DateTime;
  7. IMPORT WINAPI, SYSTEM;
  8. CONST
  9. ERR* = -7.0E5;
  10. VAR
  11. DateTable: ARRAY 120000, 3 OF INTEGER;
  12. MonthsTable: ARRAY 13, 4 OF INTEGER;
  13. PROCEDURE Encode* (Year, Month, Day, Hour, Min, Sec, MSec: INTEGER): REAL;
  14. VAR
  15. d, bis: INTEGER;
  16. res: REAL;
  17. BEGIN
  18. res := ERR;
  19. IF (Year >= 1) & (Year <= 9999) & (Month >= 1) & (Month <= 12) &
  20. (Day >= 1) & (Day <= 31) & (Hour >= 0) & (Hour <= 23) &
  21. (Min >= 0) & (Min <= 59) & (Sec >= 0) & (Sec <= 59) &
  22. (MSec >= 0) & (MSec <= 999) THEN
  23. bis := ORD((Year MOD 4 = 0) & (Year MOD 100 # 0) OR (Year MOD 400 = 0));
  24. IF Day <= MonthsTable[Month][2 + bis] THEN
  25. DEC(Year);
  26. d := Year * 365 + (Year DIV 4) - (Year DIV 100) + (Year DIV 400) +
  27. MonthsTable[Month][bis] + Day - 693594;
  28. res := FLT(d) + FLT(Hour * 3600000 + Min * 60000 + Sec * 1000 + MSec) / 86400000.0
  29. END
  30. END
  31. RETURN res
  32. END Encode;
  33. PROCEDURE Decode* (Date: REAL; VAR Year, Month, Day, Hour, Min, Sec, MSec: INTEGER): BOOLEAN;
  34. VAR
  35. res: BOOLEAN;
  36. d, t: INTEGER;
  37. L, R, M: INTEGER;
  38. BEGIN
  39. res := (Date >= -693593.0) & (Date < 2958466.0);
  40. IF res THEN
  41. d := FLOOR(Date);
  42. t := FLOOR((Date - FLT(d)) * 86400000.0);
  43. INC(d, 693593);
  44. L := 0;
  45. R := LEN(DateTable) - 1;
  46. M := (L + R) DIV 2;
  47. WHILE R - L > 1 DO
  48. IF d > DateTable[M][0] THEN
  49. L := M;
  50. M := (L + R) DIV 2
  51. ELSIF d < DateTable[M][0] THEN
  52. R := M;
  53. M := (L + R) DIV 2
  54. ELSE
  55. L := M;
  56. R := M
  57. END
  58. END;
  59. Year := DateTable[L][1];
  60. Month := DateTable[L][2];
  61. Day := d - DateTable[L][0] + 1;
  62. Hour := t DIV 3600000; t := t MOD 3600000;
  63. Min := t DIV 60000; t := t MOD 60000;
  64. Sec := t DIV 1000;
  65. MSec := t MOD 1000
  66. END
  67. RETURN res
  68. END Decode;
  69. PROCEDURE Now* (VAR Year, Month, Day, Hour, Min, Sec, MSec: INTEGER);
  70. VAR
  71. T: WINAPI.TSystemTime;
  72. BEGIN
  73. WINAPI.GetLocalTime(T);
  74. Year := ORD(T.Year);
  75. Month := ORD(T.Month);
  76. Day := ORD(T.Day);
  77. Hour := ORD(T.Hour);
  78. Min := ORD(T.Min);
  79. Sec := ORD(T.Sec);
  80. MSec := ORD(T.MSec)
  81. END Now;
  82. PROCEDURE NowEncode* (): REAL;
  83. VAR
  84. Year, Month, Day, Hour, Min, Sec, MSec: INTEGER;
  85. BEGIN
  86. Now(Year, Month, Day, Hour, Min, Sec, MSec)
  87. RETURN Encode(Year, Month, Day, Hour, Min, Sec, MSec)
  88. END NowEncode;
  89. PROCEDURE NowUnixTime* (): INTEGER;
  90. RETURN WINAPI.time(0)
  91. END NowUnixTime;
  92. PROCEDURE UnixTime* (Year, Month, Day, Hour, Min, Sec: INTEGER): INTEGER;
  93. VAR
  94. t: WINAPI.tm;
  95. BEGIN
  96. DEC(Year, 1900);
  97. DEC(Month);
  98. SYSTEM.GET(SYSTEM.ADR(Sec), t.sec);
  99. SYSTEM.GET(SYSTEM.ADR(Min), t.min);
  100. SYSTEM.GET(SYSTEM.ADR(Hour), t.hour);
  101. SYSTEM.GET(SYSTEM.ADR(Day), t.mday);
  102. SYSTEM.GET(SYSTEM.ADR(Month), t.mon);
  103. SYSTEM.GET(SYSTEM.ADR(Year), t.year);
  104. RETURN WINAPI.mktime(t)
  105. END UnixTime;
  106. PROCEDURE init;
  107. VAR
  108. day, year, month, i: INTEGER;
  109. Months: ARRAY 13 OF INTEGER;
  110. BEGIN
  111. Months[1] := 31; Months[2] := 28; Months[3] := 31; Months[4] := 30;
  112. Months[5] := 31; Months[6] := 30; Months[7] := 31; Months[8] := 31;
  113. Months[9] := 30; Months[10] := 31; Months[11] := 30; Months[12] := 31;
  114. day := 0;
  115. year := 1;
  116. month := 1;
  117. i := 0;
  118. WHILE year <= 10000 DO
  119. DateTable[i][0] := day;
  120. DateTable[i][1] := year;
  121. DateTable[i][2] := month;
  122. INC(day, Months[month]);
  123. IF (month = 2) & ((year MOD 4 = 0) & (year MOD 100 # 0) OR (year MOD 400 = 0)) THEN
  124. INC(day)
  125. END;
  126. INC(month);
  127. IF month > 12 THEN
  128. month := 1;
  129. INC(year)
  130. END;
  131. INC(i)
  132. END;
  133. MonthsTable[1][0] := 0;
  134. FOR i := 2 TO 12 DO
  135. MonthsTable[i][0] := MonthsTable[i - 1][0] + Months[i - 1]
  136. END;
  137. FOR i := 1 TO 12 DO
  138. MonthsTable[i][2] := Months[i]
  139. END;
  140. Months[2] := 29;
  141. MonthsTable[1][1] := 0;
  142. FOR i := 2 TO 12 DO
  143. MonthsTable[i][1] := MonthsTable[i - 1][1] + Months[i - 1]
  144. END;
  145. FOR i := 1 TO 12 DO
  146. MonthsTable[i][3] := Months[i]
  147. END
  148. END init;
  149. BEGIN
  150. init
  151. END DateTime.