-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathMTime.bas
1912 lines (1637 loc) · 81.2 KB
/
MTime.bas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
Attribute VB_Name = "MTime"
Option Explicit 'Lines: 1402 14.jun.2023; 1603 16.sep.2024
Public Enum ECalendar
JulianCalendar
GregorianCalendar
End Enum
Public Const HoursPerDay As Long = 24&
Public Const MinutesPerHour As Long = 60&
Public Const SecondsPerMinute As Long = 60&
Public Const SecondsPerHour As Long = SecondsPerMinute * MinutesPerHour ' 3600
Public Const SecondsPerDay As Long = SecondsPerHour * HoursPerDay ' 86400
Public Const MillisecondsPerSecond As Long = 1000&
Public Const MillisecondsPerMinute As Long = MillisecondsPerSecond * SecondsPerMinute ' 60000
Public Const MillisecondsPerHour As Long = MillisecondsPerSecond * SecondsPerHour ' 3600000
Public Const MillisecondsPerDay As Long = MillisecondsPerHour * HoursPerDay
Public Const NanosecondsPerMillisecond As Long = 1000000 ' = 1 million
Public Const NanosecondsPerSecond As Long = 1000000000 ' = 1 billion 'deutsch: 1 Milliarde
Public Const NanosecondsPerTick As Long = 100&
Public Const TicksPerMillisecond As Long = 10000& 'ten-thousand zehntausend
Public Const TicksPerSecond As Long = 10000000 'MillisecondsPerSecond * TicksPerMillisecond ' = 1 000 * 10 000 = 10 000 000 ' = 10 millions
' Date:
' Enthält IEEE-64-Bit(8-Byte)-Werte, die Datumsangaben im Bereich vom 1. Januar des Jahres 0001 bis zum 31. Dezember
' des Jahres 9999 und Uhrzeiten von 00:00:00 Uhr (Mitternacht) bis 23:59:59.9999999 Uhr darstellen.
' Jedes Inkrement stellt 100 Nanosekunden verstrichener Zeit seit Beginn des 1. Januar des Jahres 1 im gregorianischen
' Kalender dar. Der maximale Wert stellt 100 Nanosekunden vor Beginn des 1. Januar des Jahres 10000 dar.
' Verwenden Sie den Date-Datentyp, um Datumswerte, Uhrzeitwerte oder Datums-und Uhrzeitwerte einzuschließen.
' Der Standardwert von Date ist 0:00:00 (Mitternacht) am 1. Januar 0001.
' Sie erhalten das aktuelle Datum und die aktuelle Uhrzeit aus der DateAndTime-Klasse. (VBA.DateTime)
'typedef struct _FILETIME {
' DWORD dwLowDateTime;
' DWORD dwHighDateTime;
'} FILETIME, *PFILETIME;
'https://learn.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime
'Contains a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (UTC).
Public Type FILETIME
dwLowDateTime As Long ' 4
dwHighDateTime As Long ' 4
End Type 'Sum: 8
'https://learn.microsoft.com/de-de/uwp/api/windows.foundation.datetime?view=winrt-22621
'UniversalTime: A 64-bit signed integer that represents a point in time as the number of 100-nanosecond intervals prior
'to or after midnight on January 1, 1601 (according to the Gregorian Calendar).
Public Type WindowsFoundationDateTime
UniversalTime As Currency ' 8
End Type ' Sum: 8
'https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-systemtime
'typedef struct _SYSTEMTIME {
' WORD wYear;
' WORD wMonth;
' WORD wDayOfWeek;
' WORD wDay;
' WORD wHour;
' WORD wMinute;
' WORD wSecond;
' WORD wMilliseconds;
'} SYSTEMTIME, *PSYSTEMTIME;
Public Type SYSTEMTIME
wYear As Integer ' 2
wMonth As Integer ' 2
wDayOfWeek As Integer ' 2
wDay As Integer ' 2
wHour As Integer ' 2
wMinute As Integer ' 2
wSecond As Integer ' 2
wMilliseconds As Integer ' 2
End Type ' Sum: 16
Public Type DOSTIME
'https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-dosdatetimetofiletime
' Bits Description
' 0 - 4 Day of the month (1–31)
' 5 - 8 Month (1 = January, 2 = February, and so on)
' 9 -15 Year offset from 1980 (add 1980 to get actual year)
wDate As Integer ' 2
' Bits Description
' 0 - 4 Second divided by 2
' 5 -10 Minute (0–59)
'11 -15 Hour (0–23 on a 24-hour clock)
wTime As Integer ' 2
End Type ' Sum: 4
Private Type TIME_ZONE_INFORMATION
Bias As Long
StandardName(1 To 64) As Byte
StandardDate As SYSTEMTIME
StandardBias As Long
DaylightName(1 To 64) As Byte
DaylightDate As SYSTEMTIME
DaylightBias As Long
End Type
'typedef struct _TIME_DYNAMIC_ZONE_INFORMATION {
' LONG Bias;
' WCHAR StandardName[32];
' SYSTEMTIME StandardDate;
' LONG StandardBias;
' WCHAR DaylightName[32];
' SYSTEMTIME DaylightDate;
' LONG DaylightBias;
' WCHAR TimeZoneKeyName[128];
' BOOLEAN DynamicDaylightTimeDisabled;
'} DYNAMIC_TIME_ZONE_INFORMATION, *PDYNAMIC_TIME_ZONE_INFORMATION;
Private Type DYNAMIC_TIME_ZONE_INFORMATION
TZI As TIME_ZONE_INFORMATION
TimeZoneKeyName(1 To 256) As Byte
DynamicDaylightTimeDisabled As Long
End Type
Private Type THexLng
Value As Long
End Type
Private Type THexDbl
Value As Double
End Type
Private Type THexDat
Value As Date
End Type
Private Type THexBytes
Value(0 To 15) As Byte
End Type
Const TIME_ZONE_ID_UNKNOWN As Long = &H0&
Const TIME_ZONE_ID_STANDARD As Long = &H1&
Const TIME_ZONE_ID_DAYLIGHT As Long = &H2&
Private m_TZI As TIME_ZONE_INFORMATION
Private m_DynTZI As DYNAMIC_TIME_ZONE_INFORMATION
Public IsSummerTime As Boolean
#If VBA7 Then
'https://learn.microsoft.com/en-us/windows/win32/api/timezoneapi/nf-timezoneapi-gettimezoneinformation
Private Declare PtrSafe Function GetTimeZoneInformation Lib "kernel32" (lpTimeZoneInformation As TIME_ZONE_INFORMATION) As Long
'
Private Declare PtrSafe Function GetDynamicTimeZoneInformation Lib "kernel32" (pTimeZoneInformation As DYNAMIC_TIME_ZONE_INFORMATION) As Long
Private Declare PtrSafe Function GetTimeZoneInformationForYear Lib "kernel32" (ByVal wYear As Integer, pdtzi As DYNAMIC_TIME_ZONE_INFORMATION, ptzi As TIME_ZONE_INFORMATION) As Long
Private Declare PtrSafe Sub GetSystemTime Lib "kernel32" (lpSysTime As SYSTEMTIME)
Private Declare PtrSafe Function FileTimeToSystemTime Lib "kernel32" (lpFilTime As FILETIME, lpSysTime As SYSTEMTIME) As Long
Private Declare PtrSafe Function SystemTimeToFileTime Lib "kernel32" (lpSysTime As SYSTEMTIME, lpFilTime As FILETIME) As Long
'Private Declare Function FileTimeToLocalFileTime Lib "kernel32" (lpFilTime As FILETIME, lpLocFilTime As FILETIME) As Long
'Private Declare Function LocalFileTimeToFileTime Lib "kernel32" (lpLocFilTime As FILETIME, lpFilTime As FILETIME) As Long
Private Declare PtrSafe Function SystemTimeToTzSpecificLocalTime Lib "kernel32" (lpTimeZoneInformation As TIME_ZONE_INFORMATION, lpUniversalTime As SYSTEMTIME, lpLocalTime As SYSTEMTIME) As Long
Private Declare PtrSafe Function TzSpecificLocalTimeToSystemTime Lib "kernel32" (lpTimeZoneInformation As TIME_ZONE_INFORMATION, lpLocalTime As SYSTEMTIME, lpUniversalTime As SYSTEMTIME) As Long
Private Declare PtrSafe Function FileTimeToDosDateTime Lib "kernel32" (lpFileTime As FILETIME, lpFatDate As Integer, lpFatTime As Integer) As Long
Private Declare PtrSafe Function DosDateTimeToFileTime Lib "kernel32" (ByVal wFatDate As Long, ByVal wFatTime As Long, lpFilTime As FILETIME) As Long
'void GetSystemTimePreciseAsFileTime(
' [out] LPFILETIME lpSystemTimeAsFileTime
');
Private Declare PtrSafe Sub GetSystemTimePreciseAsFileTime Lib "kernel32" (lpSystemTimeAsFileTime As FILETIME)
'Private Declare Sub GetSystemTimePreciseAsFileTimeCy Lib "kernel32" Alias "GetSystemTimePreciseAsFileTime" (lpSystemTimeAsFileTime As Currency)
Private Declare PtrSafe Function QueryPerformanceCounter Lib "kernel32" (lpPerformanceCount_out As Currency) As Long
Private Declare PtrSafe Function QueryPerformanceFrequency Lib "kernel32" (lpFrequency_out As Currency) As Long
#Else
'https://learn.microsoft.com/en-us/windows/win32/api/timezoneapi/nf-timezoneapi-gettimezoneinformation
Private Declare Function GetTimeZoneInformation Lib "kernel32" (lpTimeZoneInformation As TIME_ZONE_INFORMATION) As Long
'
Private Declare Function GetDynamicTimeZoneInformation Lib "kernel32" (pTimeZoneInformation As DYNAMIC_TIME_ZONE_INFORMATION) As Long
Private Declare Function GetTimeZoneInformationForYear Lib "kernel32" (ByVal wYear As Integer, pdtzi As DYNAMIC_TIME_ZONE_INFORMATION, ptzi As TIME_ZONE_INFORMATION) As Long
Private Declare Sub GetSystemTime Lib "kernel32" (lpSysTime As SYSTEMTIME)
Private Declare Function FileTimeToSystemTime Lib "kernel32" (lpFilTime As FILETIME, lpSysTime As SYSTEMTIME) As Long
Private Declare Function SystemTimeToFileTime Lib "kernel32" (lpSysTime As SYSTEMTIME, lpFilTime As FILETIME) As Long
'Private Declare Function FileTimeToLocalFileTime Lib "kernel32" (lpFilTime As FILETIME, lpLocFilTime As FILETIME) As Long
'Private Declare Function LocalFileTimeToFileTime Lib "kernel32" (lpLocFilTime As FILETIME, lpFilTime As FILETIME) As Long
Private Declare Function SystemTimeToTzSpecificLocalTime Lib "kernel32" (lpTimeZoneInformation As TIME_ZONE_INFORMATION, lpUniversalTime As SYSTEMTIME, lpLocalTime As SYSTEMTIME) As Long
Private Declare Function TzSpecificLocalTimeToSystemTime Lib "kernel32" (lpTimeZoneInformation As TIME_ZONE_INFORMATION, lpLocalTime As SYSTEMTIME, lpUniversalTime As SYSTEMTIME) As Long
Private Declare Function FileTimeToDosDateTime Lib "kernel32" (lpFileTime As FILETIME, lpFatDate As Integer, lpFatTime As Integer) As Long
Private Declare Function DosDateTimeToFileTime Lib "kernel32" (ByVal wFatDate As Long, ByVal wFatTime As Long, lpFilTime As FILETIME) As Long
'void GetSystemTimePreciseAsFileTime(
' [out] LPFILETIME lpSystemTimeAsFileTime
');
Private Declare Sub GetSystemTimePreciseAsFileTime Lib "kernel32" (lpSystemTimeAsFileTime As FILETIME)
'Private Declare Sub GetSystemTimePreciseAsFileTimeCy Lib "kernel32" Alias "GetSystemTimePreciseAsFileTime" (lpSystemTimeAsFileTime As Currency)
Private Declare Function QueryPerformanceCounter Lib "kernel32" (lpPerformanceCount_out As Currency) As Long
Private Declare Function QueryPerformanceFrequency Lib "kernel32" (lpFrequency_out As Currency) As Long
#End If
Public Sub Init()
Dim ret As Long
'm_TZI.DaylightDate = SystemTime_Now
'm_TZI.StandardDate = SystemTime_Now
ret = GetTimeZoneInformation(m_TZI)
IsSummerTime = ret = TIME_ZONE_ID_DAYLIGHT
'Debug.Print "----------"
'Debug.Print PTimeZoneInfo_ToStr(m_TZI)
ret = GetDynamicTimeZoneInformation(m_DynTZI)
IsSummerTime = ret = TIME_ZONE_ID_DAYLIGHT
'Debug.Print "----------"
'Debug.Print PDynTimeZoneInfo_ToStr(m_DynTZI)
Dim y As Integer: y = DateTime.Year(Now)
ret = GetTimeZoneInformationForYear(y, m_DynTZI, m_TZI)
'Debug.Print "----------"
'Debug.Print PTimeZoneInfo_ToStr(m_TZI)
'Debug.Print PDynTimeZoneInfo_ToStr(m_DynTZI)
If IsSummerTime Or ret = TIME_ZONE_ID_STANDARD Or ret = TIME_ZONE_ID_UNKNOWN Then Exit Sub
MsgBox "Error trying to get time-zone-info!" & vbCrLf & ret
End Sub
' get accurate timer
Public Function GetTimer() As Double
Dim f As Currency: QueryPerformanceFrequency f
Dim n As Currency: QueryPerformanceCounter n
GetTimer = n / f
End Function
Public Function TimeZoneInfo_ConvertTimeToUtc(ByVal this As Date) As Date
TimeZoneInfo_ConvertTimeToUtc = SystemTime_ToDate(TzSpecificLocalTime_ToSystemTime(Date_ToSystemTime(this)))
End Function
Public Property Get TimeZoneInfo_Bias() As Long
TimeZoneInfo_Bias = m_DynTZI.TZI.Bias
End Property
Public Property Get TimeZoneInfo_StandarBias() As Long
TimeZoneInfo_StandarBias = m_DynTZI.TZI.StandardBias
End Property
Public Property Get TimeZoneInfo_DaylightBias() As Long
TimeZoneInfo_DaylightBias = m_DynTZI.TZI.DaylightBias
End Property
Public Function TimeZoneInfo_ToStr() As String
TimeZoneInfo_ToStr = PTimeZoneInfo_ToStr(m_TZI)
End Function
Private Function PTimeZoneInfo_ToStr(this As TIME_ZONE_INFORMATION) As String
Dim S As String
With this
S = S & "Bias : " & .Bias & vbCrLf
S = S & "StandardName : " & Trim0(.StandardName) & vbCrLf
S = S & "StandardDate : " & TimeZoneInfoSystemTime_ToDate(.StandardDate) & vbCrLf
S = S & "StandardBias : " & .StandardBias & vbCrLf
S = S & "DaylightName : " & Trim0(.DaylightName) & vbCrLf
S = S & "DaylightDate : " & TimeZoneInfoSystemTime_ToDate(.DaylightDate) & vbCrLf
S = S & "DaylightBias : " & .DaylightBias & vbCrLf
End With
PTimeZoneInfo_ToStr = S
End Function
Public Function DynTimeZoneInfo_ToStr() As String
DynTimeZoneInfo_ToStr = PDynTimeZoneInfo_ToStr(m_DynTZI)
End Function
Private Function PDynTimeZoneInfo_ToStr(this As DYNAMIC_TIME_ZONE_INFORMATION) As String
Dim S As String
With this
S = S & PTimeZoneInfo_ToStr(.TZI)
S = S & "TimeZoneKeyName : " & Trim0(.TimeZoneKeyName) & vbCrLf
S = S & "TimeZoneKeyName : " & .DynamicDaylightTimeDisabled & vbCrLf
S = S & "IsSummerTime : " & IsSummerTime & vbCrLf
End With
PDynTimeZoneInfo_ToStr = S
End Function
Function Trim0(ByVal S As String) As String
Trim0 = Trim(S)
If Right(Trim0, 1) = vbNullChar Then
Trim0 = Left(Trim0, Len(Trim0) - 1)
Trim0 = Trim0(Trim0)
'Else
' Exit Function
End If
End Function
'Public Function GetSystemUpTime() As Date
Public Function GetSystemUpTime() As String
'Returns the timespan since the last new start of your pc
Dim ms As Currency 'milliseconds since system new start
QueryPerformanceCounter ms
Dim d As Long: d = ms \ MillisecondsPerDay: ms = ms - CCur(d) * CCur(MillisecondsPerDay)
Dim H As Long: H = ms \ MillisecondsPerHour: ms = ms - H * MillisecondsPerHour
Dim m As Long: m = ms \ MillisecondsPerMinute: ms = ms - m * MillisecondsPerMinute
Dim S As Long: S = ms \ MillisecondsPerSecond: ms = ms - S * MillisecondsPerSecond
GetSystemUpTime = d & ":" & Format(H, "00") & ":" & Format(m, "00") & ":" & Format(S, "00") & "." & Format(ms, "000")
End Function
' Dim d As Date ' empty date!
' MsgBox FormatDateTime(d, VBA.VbDateTimeFormat.vbLongDate) & " " & FormatDateTime(d, VBA.VbDateTimeFormat.vbLongTime)
' 'Samstag, 30. Dezember 1899 00:00:00
Public Function GetPCStartTime() As Date
Dim ms As Currency 'milliseconds since system new start
QueryPerformanceCounter ms
Dim d As Long: d = ms \ MillisecondsPerDay: ms = ms - d * MillisecondsPerDay
Dim H As Long: H = ms \ MillisecondsPerHour: ms = ms - H * MillisecondsPerHour
Dim m As Long: m = ms \ MillisecondsPerMinute: ms = ms - m * MillisecondsPerMinute
Dim S As Long: S = ms \ MillisecondsPerSecond: ms = ms - S * MillisecondsPerSecond
GetPCStartTime = VBA.DateTime.Now - DateSerial(1900, 1, d - 1) - TimeSerial(H, m, S)
End Function
' ############################## ' DateTimeStamp ' ############################## '
' e.g. can be found in executable files, exe, dll
Public Function DateTimeStamp(ByVal Year As Integer, ByVal Month As Integer, ByVal Day As Integer, ByVal Hour As Integer, ByVal Minute As Integer, ByVal Second As Integer) As Long
DateTimeStamp = Date_ToDateTimeStamp(New_Date(Year, Month, Day, Hour, Minute, Second))
End Function
Public Function DateTimeStamp_Now() As Long
DateTimeStamp_Now = Date_ToDateTimeStamp(Date_Now)
End Function
Public Function DateTimeStamp_ToDate(ByVal DtStamp As Long) As Date
Dim l0 As Long: l0 = DtStamp \ SecondsPerDay
Dim l1 As Long: l1 = DtStamp - l0 * SecondsPerDay
Dim l2 As Long: l2 = DateSerial(1970, 1, 2)
DateTimeStamp_ToDate = l0 + Sgn(l1) + l1 / SecondsPerDay + l2
End Function
Public Function DateTimeStamp_ToSystemTime(ByVal DtStamp As Long) As SYSTEMTIME
DateTimeStamp_ToSystemTime = Date_ToSystemTime(DateTimeStamp_ToDate(DtStamp))
End Function
Public Function DateTimeStamp_ToFileTime(ByVal DtStamp As Long) As FILETIME
DateTimeStamp_ToFileTime = Date_ToFileTime(DateTimeStamp_ToDate(DtStamp))
End Function
Public Function DateTimeStamp_ToUnixTime(ByVal DtStamp As Long) As Double
DateTimeStamp_ToUnixTime = Date_ToUnixTime(DateTimeStamp_ToDate(DtStamp))
End Function
Public Function DateTimeStamp_ToDosTime(ByVal DtStamp As Long) As DOSTIME
DateTimeStamp_ToDosTime = Date_ToDosTime(DateTimeStamp_ToDate(DtStamp))
End Function
Public Function DateTimeStamp_ToUniversalTimeCoordinated(DtStamp As Long) As SYSTEMTIME
Dim syt As SYSTEMTIME: syt = DateTimeStamp_ToSystemTime(DtStamp)
DateTimeStamp_ToUniversalTimeCoordinated = MTime.SystemTime_ToUniversalTimeCoordinated(syt)
End Function
Public Function DateTimeStamp_ToWindowsFoundationDateTime(ByVal DtStamp As Long) As WindowsFoundationDateTime
DateTimeStamp_ToWindowsFoundationDateTime = Date_ToWindowsFoundationDateTime(DateTimeStamp_ToDate(DtStamp))
End Function
Public Function DateTimeStamp_ToStr(ByVal DtStamp As Long) As String
'Dim l0 As Long: l0 = DTStamp \ SecondsPerDay
'Dim l1 As Long: l1 = DTStamp - l0 * SecondsPerDay
'Dim l2 As Long: l2 = DateSerial(1970, 1, 2)
'Dim gmt As Date: gmt = l0 + Sgn(l1) + l1 / SecondsPerDay + l2
'DateTimeStamp_ToStr = Format$(gmt, "yyyy.mm.dd - hh:mm:ss")
DateTimeStamp_ToStr = Format$(DateTimeStamp_ToDate(DtStamp), "yyyy.mm.dd - hh:mm:ss")
'DateTimeStamp_ToStr = "&&H" & Hex(DTStamp)
End Function
Public Function DateTimeStamp_ToHex(ByVal DtStamp As Long) As String
Dim th As THexBytes, tl As THexLng: tl.Value = DtStamp: LSet th = tl
DateTimeStamp_ToHex = THexBytes_ToStr(th)
End Function
Public Function DateTimeStamp_ToHexNStr(ByVal DtStamp As Long) As String
DateTimeStamp_ToHexNStr = DateTimeStamp_ToHex(DtStamp) & "; " & DateTimeStamp_ToStr(DtStamp)
End Function
Public Function DateTimeStamp_ToStrISO8601(ByVal DtStamp As Long) As String
DateTimeStamp_ToStrISO8601 = SystemTime_ToStrISO8601(DateTimeStamp_ToSystemTime(DtStamp))
End Function
' ############################## ' Date ' ############################## '
Public Function New_Date(ByVal Year As Integer, ByVal Month As Integer, ByVal Day As Integer, ByVal Hour As Integer, ByVal Minute As Integer, ByVal Second As Integer) As Date
New_Date = DateSerial(Year, Month, Day) + TimeSerial(Hour, Minute, Second)
End Function
Public Property Get Date_Now() As Date
Date_Now = VBA.DateTime.Now
End Property
Public Function Date_ToSystemTime(this As Date) As SYSTEMTIME
With Date_ToSystemTime
.wYear = Year(this)
.wMonth = Month(this)
.wDayOfWeek = Weekday(this, vbUseSystemDayOfWeek)
.wDay = Day(this)
.wHour = Hour(this)
.wMinute = Minute(this)
.wSecond = Second(this)
'.wMilliseconds = millisecond(aDate) 'nope
End With
End Function
Public Function Date_ToFileTime(this As Date) As FILETIME
SystemTimeToFileTime Date_ToSystemTime(this), Date_ToFileTime
End Function
Public Function Date_ToUniversalTimeCoordinated(this As Date) As SYSTEMTIME
'Dim dat As Date: dat = TimeZoneInfo_ConvertTimeToUtc(aDate)
Date_ToUniversalTimeCoordinated = Date_ToSystemTime(TimeZoneInfo_ConvertTimeToUtc(this))
End Function
Public Function Date_ToUnixTime(this As Date) As Double
Date_ToUnixTime = DateDiff("s", DateSerial(1970, 1, 1), this) - GetSummerTimeCorrector
End Function
Public Function Date_ToDosTime(this As Date) As DOSTIME
Date_ToDosTime = FileTime_ToDosTime(Date_ToFileTime(this))
End Function
Public Function Date_ToDateTimeStamp(this As Date) As Long
Date_ToDateTimeStamp = DateDiff("s", DateSerial(1970, 1, 2), this)
End Function
Public Function Date_ToWindowsFoundationDateTime(this As Date) As WindowsFoundationDateTime
LSet Date_ToWindowsFoundationDateTime = Date_ToFileTime(this)
End Function
Public Function Date_ToStr(this As Date) As String
Date_ToStr = FormatDateTime(this, VbDateTimeFormat.vbLongDate) & " - " & FormatDateTime(this, VbDateTimeFormat.vbLongTime)
End Function
Public Function GetSummerTimeCorrector() As Double
GetSummerTimeCorrector = DateDiff("s", SystemTime_ToDate(SystemTime_Now), Now)
End Function
Public Function Date_BiasMinutesToUTC(ByVal this As Date) As Long
Dim utc As Date: utc = MTime.TimeZoneInfo_ConvertTimeToUtc(this)
Date_BiasMinutesToUTC = DateDiff("n", utc, this)
End Function
Public Function Date_Equals(this As Date, other As Date) As Boolean
Date_Equals = this = other
End Function
Public Function Date_ToHex(ByVal this As Date) As String
Dim th As THexBytes, td As THexDat: td.Value = this: LSet th = td
Date_ToHex = THexBytes_ToStr(th)
End Function
Public Function Date_ToHexNStr(ByVal this As Date) As String
Date_ToHexNStr = Date_ToHex(this) & "; " & Date_ToStr(this)
End Function
Public Function Date_FormatISO8601(ByVal this As Date, Optional doFormatDate As Boolean = True, Optional doFormatTime As Boolean = True, Optional ByVal DateSeparator As String = "-", Optional ByVal TimeSeparator As String = ":") As String
Dim fmt As String
If doFormatDate Then
fmt = "YYYY" & DateSeparator & "MM" & DateSeparator & "DD" & IIf(doFormatTime, "T", "")
End If
If doFormatTime Then
fmt = fmt & "hh" & TimeSeparator & "mm" & TimeSeparator & "ss"
End If
Date_FormatISO8601 = Format(this, fmt)
End Function
Public Function Date_Format(ByVal this As Date, ByVal FormatStr As String) As String
Dim S As String, y As Integer
Select Case FormatStr
Case "YYYY-Www": S = Year(this) & "-W" & WeekOfYear(this)
'Case "YYYY-Www": ' 2004-07-11 -YYYY-MM-DD -0333-07-11 ' 2004-W28 - YYYY-Www - 0333-W28
Case "YYYYWww": S = Year(this) & "W" & WeekOfYear(this)
'Case "YYYYWww": ' 2004-07-11 -YYYY-MM-DD -0333-07-11 ' 2004W28 - YYYYWww -0333W28
Case "YYYY-Www-D": S = Year(this) & "-W" & WeekOfYear(this) & "-" & DayOfWeek(Year(this), Month(this), Day(this))
' 2004-07-11 -YYYY-MM-DD -0333-07-11 ' 2004-W28-7 - YYYY-Www-D -0333-W28-7
Case "YYYYWwwD": S = Year(this) & "W" & WeekOfYear(this) & DayOfWeek(Year(this), Month(this), Day(this))
' 2004-07-11 -YYYY-MM-DD -0333-07-11 ' 2004W287 - YYYYWwwD -0333W287
Case "YYYY-DDD": S = Year(this) & "-" & DayOfYear(this)
' 2004-07-11 -YYYY-MM-DD -0333-07-11 ' 2004-193 - YYYY-DDD -0333-193
Case "YYYYDDD": S = Year(this) & DayOfYear(this)
' 2004-07-11 -YYYY-MM-DD -0333-07-11 ' 2004193 - YYYYDDD - 333193
Case Else: S = Format(this, FormatStr)
End Select
Date_Format = S
End Function
Public Function Date_ParseFromISO8601(ByVal S As String) As Date
Try: On Error GoTo Catch
S = Trim$(S)
Dim ye As Integer, mo As Integer, da As Integer, woy As Integer
Dim ho As Integer, mn As Integer, se As Integer
Dim DatTimSep As String: DatTimSep = GetDateTimeSeparator(S)
Dim sa() As String
If Len(DatTimSep) Then
sa = Split(S, DatTimSep)
Dim u As Long: u = UBound(sa)
Dim sDate As String: If u > 0 Then sDate = sa(0)
Dim sTime As String: If u > 0 Then sTime = sa(1)
Dim lDate As Long: lDate = Len(sDate)
Dim lTime As Long: lTime = Len(sTime)
'Dim dDate As Date: dDate = MTime.d
'Dim dTime As Date
If lDate Then
Dim DatSep As String: DatSep = GetDateSeparator(sDate)
If Len(DatSep) Then
sa = Split(sDate, DatSep)
Dim ud As Long: ud = UBound(sa)
If ud > 0 Then ye = CInt(sa(0))
If ud > 0 Then mo = CInt(sa(1))
If ud > 1 Then da = CInt(sa(2))
Else
If Not IsNumeric(sDate) Then Exit Function
Select Case lDate
Case 8: ye = CInt(Left(sDate, 4))
mo = CInt(Mid(sDate, 5, 2))
da = CInt(Mid(sDate, 7, 2))
Case 7: ye = CInt(Left(sDate, 4))
Dim doy As Integer: doy = CLng(Mid(sDate, 5))
If doy > 367 Then Exit Function
Dim tmp As Date: tmp = Date_FromDayOfYear(ye, doy): Exit Function
mo = Month(tmp)
da = Day(tmp)
Case 6: ye = CLng(Left(sDate, 2))
ye = ye + IIf(ye < 35, 2000, 1900)
mo = CLng(Mid(sDate, 3, 2))
da = CLng(Mid(sDate, 5, 2))
End Select
End If
End If
If lTime Then
Dim TimSep As String: TimSep = GetTimeSeparator(sTime)
If Len(TimSep) Then
sa = Split(sTime, TimSep)
Dim ut As Long: ut = UBound(sa)
If ut > 0 Then ho = CInt(sa(0))
If ut > 0 Then mn = CInt(sa(1))
If ut > 1 Then se = CInt(sa(2))
Else
If Not IsNumeric(sTime) Then Exit Function
If lTime > 1 Then ho = CInt(Left(sTime, 2))
If lTime > 3 Then mn = CInt(Mid(sTime, 3, 2))
If lTime > 5 Then se = CInt(Mid(sTime, 5, 2))
End If
End If
Else
If Not IsNumeric(S) Then
If Str_Contains(S, "W") Then
sa = Split(S, "W")
ye = sa(0)
If UBound(sa) > 0 Then woy = sa(1)
Date_ParseFromISO8601 = Date_FromWeekOfYear(ye, woy)
Else
If Len(S) = 7 And Str_Contains(S, "-") Then
sa = Split(S, "-")
ye = sa(0)
If UBound(sa) > 0 Then woy = sa(1)
Date_ParseFromISO8601 = Date_FromWeekOfYear(ye, woy)
Else
Date_ParseFromISO8601 = CDate(S)
End If
End If
Exit Function
Else
If Len(S) > 3 Then ye = CInt(Left(S, 4))
If Len(S) > 5 Then mo = CInt(Mid(S, 5, 2))
If Len(S) > 7 Then da = CInt(Mid(S, 7, 2))
If Len(S) > 9 Then ho = CInt(Mid(S, 9, 2))
If Len(S) > 11 Then mn = CInt(Mid(S, 11, 2))
If Len(S) > 13 Then se = CInt(Mid(S, 13, 2))
End If
End If
Date_ParseFromISO8601 = New_Date(ye, mo, da, ho, mn, se)
Catch:
End Function
Private Function GetDateTimeSeparator(S As String) As String
GetDateTimeSeparator = " "
If Str_Contains(S, GetDateTimeSeparator) Then Exit Function
GetDateTimeSeparator = "T"
If Str_Contains(S, GetDateTimeSeparator) Then Exit Function
GetDateTimeSeparator = "P"
If Str_Contains(S, GetDateTimeSeparator) Then Exit Function
GetDateTimeSeparator = ""
End Function
Private Function GetDateSeparator(S As String) As String
GetDateSeparator = "-"
If Str_Contains(S, GetDateSeparator) Then Exit Function
GetDateSeparator = "."
If Str_Contains(S, GetDateSeparator) Then Exit Function
GetDateSeparator = "/"
If Str_Contains(S, GetDateSeparator) Then Exit Function
GetDateSeparator = "\"
If Str_Contains(S, GetDateSeparator) Then Exit Function
GetDateSeparator = ""
Dim i As Long, char As Long
For i = 1 To Len(S)
char = AscW(Mid(S, i, 1))
Select Case char
Case 48 To 57 '0-9
Case Else: GetDateSeparator = ChrW(char): Exit Function
End Select
Next
End Function
Private Function GetTimeSeparator(S As String) As String
GetTimeSeparator = ":"
If Str_Contains(S, GetTimeSeparator) Then Exit Function
GetTimeSeparator = "."
If Str_Contains(S, GetTimeSeparator) Then Exit Function
GetTimeSeparator = "/"
If Str_Contains(S, GetTimeSeparator) Then Exit Function
GetTimeSeparator = "\"
If Str_Contains(S, GetTimeSeparator) Then Exit Function
GetTimeSeparator = "-"
If Str_Contains(S, GetTimeSeparator) Then Exit Function
GetTimeSeparator = ""
Dim i As Long, char As Long
For i = 1 To Len(S)
char = AscW(Mid(S, i, 1))
Select Case char
Case 48 To 57 '0-9
Case Else: GetTimeSeparator = ChrW(char): Exit Function
End Select
Next
End Function
Private Function Str_Contains(this As String, ByVal Value As String) As Boolean
Str_Contains = InStr(1, this, Value) > 0
End Function
' ############################## ' MDate ' ############################## '
Public Function ECalendar_ToStr(e As ECalendar) As String
Dim S As String
Select Case e
Case ECalendar.GregorianCalendar: S = "GregorianCalendar"
Case ECalendar.JulianCalendar: S = "JulianCalendar"
End Select
ECalendar_ToStr = S
End Function
Public Function ECalendar_Parse(S As String) As ECalendar
Dim e As ECalendar
Select Case S
Case "GregorianCalendar": e = ECalendar.GregorianCalendar
Case "JulianCalendar": e = ECalendar.JulianCalendar
End Select
ECalendar_Parse = e
End Function
Public Function CalcEasterdateGauss1800(ByVal y As Long, Optional ByVal ecal As ECalendar = ECalendar.GregorianCalendar) As Date
Dim A As Long: A = y Mod 19 'der Mondparameter
Dim b As Long: b = y Mod 4
Dim c As Long: c = y Mod 7
Dim k As Long: k = y \ 100 'die Säkularzahl
Dim p As Long
Dim q As Long
Dim m As Long 'die säkulare Mondschaltung
Dim d As Long 'der Keim für den ersten Vollmond im Frühling
Dim n As Long
Dim e As Long
Dim OS As Long 'das Datum des Ostersonntags als Märzdatum
Dim EasterMonth As Long
Select Case ecal
Case ECalendar.JulianCalendar
m = 15
Case ECalendar.GregorianCalendar
p = k \ 3
q = k \ 4
m = (15 + k - p - q) Mod 30
End Select
d = (19 * A + m) Mod 30
Select Case ecal
Case ECalendar.JulianCalendar
n = 6
Case ECalendar.GregorianCalendar
n = (4 + k - q) Mod 7
End Select
e = (2 * b + 4 * c + 6 * d + n) Mod 7
OS = (22 + d + e)
EasterMonth = 3
If OS > 31 Then
OS = OS - 31
EasterMonth = 4
End If
Dim easter As Date: easter = OS & "." & EasterMonth & "." & y
CalcEasterdateGauss1800 = easter
End Function
Public Function CalcEasterdateGauss1816(ByVal y As Long, Optional ByVal ecal As ECalendar = ECalendar.GregorianCalendar) As Date
Dim A As Long: A = y Mod 19 'der Mondparameter / Gaußsche Zykluszahl
Dim b As Long: b = y Mod 4
Dim c As Long: c = y Mod 7
Dim k As Long: k = y \ 100 'die Säkularzahl
Dim p As Long
Dim q As Long
Dim m As Long 'die säkulare Mondschaltung
Dim d As Long 'der Keim für den ersten Vollmond im Frühling
Dim n As Long
Dim e As Long
Dim OS As Long 'das Datum des Ostersonntags als Märzdatum
Dim EasterMonth As Long
Select Case ecal
Case ECalendar.JulianCalendar
m = 15
Case ECalendar.GregorianCalendar
p = (8 * k + 13) \ 25 'hier unterschiedlich zu 1800
q = k \ 4
m = (15 + k - p - q) Mod 30
End Select
d = (19 * A + m) Mod 30
Select Case ecal
Case ECalendar.JulianCalendar
n = 6
Case ECalendar.GregorianCalendar
n = (4 + k - q) Mod 7
End Select
e = (2 * b + 4 * c + 6 * d + n) Mod 7
OS = (22 + d + e)
CalcEasterdateGauss1816 = CorrectOSDay(OS, y)
End Function
'Schritt Bedeutung Formel
'1. die Säkularzahl K(X) = X div 100
'2. die säkulare Mondschaltung M(K) = 15 + (3K + 3) div 4 - (8K + 13) div 25
'3. die säkulare Sonnenschaltung S(K) = 2 - (3K + 3) div 4
'4. den Mondparameter A(X) = X mod 19
'5. den Keim für den ersten Vollmond im Frühling D(A,M) = (19A + M) mod 30
'6. die kalendarische Korrekturgröße R(D,A) = (D + A div 11) div 29[13]
'7. die Ostergrenze OG(D,R) = 21 + D - R
'8. den ersten Sonntag im März SZ(X,S) = 7 - (X + X div 4 + S) mod 7
'9. die Entfernung des Ostersonntags von der Ostergrenze
' (Osterentfernung in Tagen) OE(OG,SZ) = 7 - (OG - SZ) mod 7
'10. das Datum des Ostersonntags als Märzdatum
' (32. März = 1. April usw.) OS = OG + OE
Public Function CalcEasterdateGaussCorrected1900(ByVal y As Long, Optional ByVal ecal As ECalendar = ECalendar.GregorianCalendar) As Date
Dim A As Long: A = y Mod 19 'der Mondparameter / Gaußsche Zykluszahl
'Dim b As Long: b = y Mod 4
'Dim c As Long: c = y Mod 7
Dim k As Long: k = y \ 100 'die Säkularzahl
Dim p As Long
Dim q As Long
Dim m As Long 'die säkulare Mondschaltung
Dim S As Long 'die säkulare Sonnenschaltung
Dim d As Long 'der Keim für den ersten Vollmond im Frühling
Dim r As Long 'die kalendarische Korrekturgröße
Dim OG As Long 'die Ostergrenze
Dim SZ As Long 'der erste Sonntag im März
Dim OE As Long 'die Entfernung des Ostersonntags von der Ostergrenze (Osterentfernung in Tagen)
Dim OS As Long 'das Datum des Ostersonntags als Märzdatum
Dim n As Long
Dim e As Long
Dim EasterMonth As Long
Select Case ecal
Case ECalendar.JulianCalendar
m = 15
S = 0
Case ECalendar.GregorianCalendar
p = (8 * k + 13) \ 25 'hier unterschiedlich zu 1800
q = (3 * k + 3) \ 4
m = 15 + q - p
S = 2 - q
End Select
d = (19 * A + m) Mod 30
r = (d + A \ 11) \ 29
OG = 21 + d - r
SZ = 7 - (y + y \ 4 + S) Mod 7
OE = 7 - (OG - SZ) Mod 7
OS = OG + OE
CalcEasterdateGaussCorrected1900 = CorrectOSDay(OS, y)
End Function
Public Function CorrectOSDay(ByVal OS_Mrz As Long, ByVal y As Long) As Date
Dim OSDay As Long: OSDay = OS_Mrz + 31 * (OS_Mrz > 31)
Dim OSMonth As Long: OSMonth = 3 - (OS_Mrz > 31)
CorrectOSDay = DateSerial(y, OSMonth, OSDay)
End Function
Public Function OsternShort(ByVal y As Long, Optional ByVal ecal As ECalendar = ECalendar.GregorianCalendar) As Date
'code taken from CalcEasterdateGaussCorrected1900 + CorrectOSDay
'and then shortened
Dim m As Long 'die säkulare Mondschaltung
Dim S As Long 'die säkulare Sonnenschaltung
Select Case ecal
Case ECalendar.JulianCalendar
m = 15
S = 0
Case ECalendar.GregorianCalendar
Dim k As Long: k = y \ 100 'die Säkularzahl
Dim p As Long: p = (8 * k + 13) \ 25 'hier unterschiedlich zu 1800
Dim q As Long: q = (3 * k + 3) \ 4
m = 15 + q - p
S = 2 - q
End Select
Dim A As Long: A = y Mod 19 'der Mondparameter / Gaußsche Zykluszahl
Dim d As Long: d = (19 * A + m) Mod 30 'der Keim für den ersten Vollmond im Frühling
Dim r As Long: r = (d + A \ 11) \ 29 'die kalendarische Korrekturgröße
Dim OG As Long: OG = 21 + d - r 'die Ostergrenze
Dim SZ As Long: SZ = 7 - (y + y \ 4 + S) Mod 7 'der erste Sonntag im März
Dim OE As Long: OE = 7 - (OG - SZ) Mod 7 'die Entfernung des Ostersonntags von der Ostergrenze (Osterentfernung in Tagen)
Dim OS As Long: OS = OG + OE 'das Datum des Ostersonntags als Märzdatum
Dim OS_Mrz As Long: OS_Mrz = OS
Dim OSDay As Long: OSDay = OS_Mrz + 31 * (OS_Mrz > 31)
Dim OSMonth As Long: OSMonth = 3 - (OS_Mrz > 31)
OsternShort = DateSerial(y, OSMonth, OSDay)
End Function
Public Function OsternShort2(ByVal y As Long) As Date
'let's say we only want to have GregorianCalendar
'code taken from CalcEasterdateGaussCorrected1900 and CorrectOSDay and then shortened it
Dim k As Long: k = y \ 100 'die Säkularzahl
'(8 * k + 13) \ 25 'hier unterschiedlich zu 1800
Dim q As Long: q = (3 * k + 3) \ 4
'2 - q '= die säkulare Sonnenschaltung
Dim A As Long: A = y Mod 19 'der Mondparameter / Gaußsche Zykluszahl
'15 + q - ((8 * k + 13) \ 25) '= die säkulare Mondschaltung
Dim d As Long: d = (19 * A + (15 + q - ((8 * k + 13) \ 25))) Mod 30 'der Keim für den ersten Vollmond im Frühling
'(d + a \ 11) \ 29 'die kalendarische Korrekturgröße
Dim OG As Long: OG = 21 + d - (d + A \ 11) \ 29 'die Ostergrenze
'7 - (y + y \ 4 + (2 - q)) Mod 7 'der erste Sonntag im März
Dim OE As Long: OE = 7 - (OG - (7 - (y + y \ 4 + (2 - q)) Mod 7)) Mod 7 'die Entfernung des Ostersonntags von der Ostergrenze (Osterentfernung in Tagen)
Dim OS As Long: OS = OG + OE 'das Datum des Ostersonntags als Märzdatum
OsternShort2 = DateSerial(y, (3 - (OS > 31)), (OS + 31 * (OS > 31)))
End Function
Public Function AdventSunday1(ByVal Year As Integer) As Date
Dim Nov26 As Date: Nov26 = DateSerial(Year, 11, 26)
Dim wd As VbDayOfWeek: wd = Weekday(Nov26, VbDayOfWeek.vbMonday)
AdventSunday1 = Nov26 + 7 - wd
End Function
Public Function Mothersday(ByVal Year As Integer) As Date
Dim May1 As Date: May1 = DateSerial(Year, 5, 1)
Mothersday = May1 + 15 - Weekday(May1)
End Function
Public Function Date_FromDayOfYear(ByVal Year As Integer, ByVal DayOfYear As Integer) As Date
Dim mds As Integer
mds = 31
If DayOfYear <= mds Then Date_FromDayOfYear = DateSerial(Year, 1, DayOfYear): Exit Function
DayOfYear = DayOfYear - mds
mds = 28 - CInt(IsLeapYear(Year))
If DayOfYear <= mds Then Date_FromDayOfYear = DateSerial(Year, 2, DayOfYear): Exit Function
DayOfYear = DayOfYear - mds
mds = 31
If DayOfYear <= mds Then Date_FromDayOfYear = DateSerial(Year, 3, DayOfYear): Exit Function
DayOfYear = DayOfYear - mds
mds = 30
If DayOfYear <= mds Then Date_FromDayOfYear = DateSerial(Year, 4, DayOfYear): Exit Function
DayOfYear = DayOfYear - mds
mds = 31
If DayOfYear <= mds Then Date_FromDayOfYear = DateSerial(Year, 5, DayOfYear): Exit Function
DayOfYear = DayOfYear - mds
mds = 30
If DayOfYear <= mds Then Date_FromDayOfYear = DateSerial(Year, 6, DayOfYear): Exit Function
DayOfYear = DayOfYear - mds
mds = 31
If DayOfYear <= mds Then Date_FromDayOfYear = DateSerial(Year, 7, DayOfYear): Exit Function
DayOfYear = DayOfYear - mds
mds = 31
If DayOfYear <= mds Then Date_FromDayOfYear = DateSerial(Year, 8, DayOfYear): Exit Function
DayOfYear = DayOfYear - mds
mds = 30
If DayOfYear <= mds Then Date_FromDayOfYear = DateSerial(Year, 9, DayOfYear): Exit Function
DayOfYear = DayOfYear - mds
mds = 31
If DayOfYear <= mds Then Date_FromDayOfYear = DateSerial(Year, 10, DayOfYear): Exit Function
DayOfYear = DayOfYear - mds
mds = 30
If DayOfYear <= mds Then Date_FromDayOfYear = DateSerial(Year, 11, DayOfYear): Exit Function
DayOfYear = DayOfYear - mds
mds = 31
If DayOfYear <= mds Then Date_FromDayOfYear = DateSerial(Year, 12, DayOfYear): Exit Function
End Function
'Public Function Date_FromDayOfYear(ByVal Year As Integer, ByVal doy As Integer) As Date
' Dim m As Integer, nd As Long, nd1 As Long
' For m = 0 To 11
' nd1 = nd + DaysInMonth(Year, m + 1)
' If (nd < doy) And (doy <= nd1) Then Exit For
' nd = nd1
' Next
' Dim d As Integer: d = doy - nd
' Date_FromDayOfYear = DateSerial(Year, m + 1, d)
'End Function
Public Function Date_FromWeekOfYear(ByVal Year As Integer, ByVal woy As Integer) As Date
Date_FromWeekOfYear = Date_FromDayOfYear(Year, 7 * woy)
End Function
Public Function Date_TryParse(ByVal S As String, ByRef out_date As Date) As Boolean
Try: On Error GoTo Catch
If LCase(S) = "now" Or LCase(S) = "jetzt" Then out_date = Now: Exit Function
out_date = CDate(S)
Date_TryParse = True
Exit Function
Catch:
MsgBox Err.Number & " " & Err.Description
End Function
Public Function Time_TryParse(ByVal S As String, out_time As Date) As Boolean
Try: On Error GoTo Catch
If Len(S) = 0 Then Exit Function
If LCase(S) = "now" Or LCase(S) = "jetzt" Then S = Now
Dim sa() As String: sa = Split(S, ":")
Dim u As Long: u = UBound(sa)
Dim hh As String: hh = sa(0)
If u > 0 Then
Dim mm As String: mm = sa(1)
If u > 1 Then
Dim ss As String: ss = sa(2)
Dim hhh As Integer: hhh = CInt(hh)
Dim mmm As Integer: mmm = CInt(mm)
Dim sss As Integer: sss = CInt(ss)
out_time = TimeSerial(hhh, mmm, sss)
Time_TryParse = True
Exit Function
End If
End If
'out_date = CDate(s)
Time_TryParse = True
Exit Function
Catch:
MsgBox Err.Number & " " & Err.Description
End Function
Public Function Date_JulianDay(ByVal dt As Date) As Double
Dim dat As Date: dat = DateSerial(Year(dt), Month(dt), Day(dt))
Dim tim As Date: tim = TimeSerial(Hour(dt), Minute(dt), Second(dt))
Dim UtcOffset As Double: UtcOffset = Date_BiasMinutesToUTC(dt) / 60
Date_JulianDay = dat + 2415018.5 + tim - UtcOffset / 24
End Function
Public Function Date_JulianCentury(ByVal dt As Date) As Double
Dim jd As Double: jd = Date_JulianDay(dt)
Date_JulianCentury = (jd - 2451545#) / 36525#
End Function
'Many thanks to idiv alias Chris for the following function
'unsigned int GetDayOfWeek(unsigned int Year, unsigned int Month, unsigned int Day)
'{
' unsigned int y, c;
'
' if ((Month > 0) && (Month <= 12))
' {
' if ((Day > 0) && (Day <= GetMonthDayCount(Year, Month)))
' {
' y = (Year % 100);
' c = Year / 100;
'
' if (Month > 2)
' Month -= 2;
' Else
' {
' Month += 10;
' if (y > 0)
' y--;
' Else
' {
' y = 99;
' c--;
' }
' }