forked from eselje/FoxTypes
-
Notifications
You must be signed in to change notification settings - Fork 0
/
datetime.PRG
345 lines (273 loc) · 6.86 KB
/
datetime.PRG
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
#DEFINE STARTOFTIME {^1970-1-1 00:00:00}
DEFINE CLASS DateTime AS StaticVariable OF Static.prg
PROTECTED oString
Value = { :}
Date = { }
Day = 0
DayOfWeek = 0
DayOfYear = 0
Hour = 0
Kind = ""
Millisecond = 0
Minute = 0
Month = 0
Second = 0
Ticks = 0
TimeOfDay = 0
Today = {}
UtcNow = { :}
Year = 0
cTimeZone = ""
iTimeZoneOffset = .null.
lDaylightSavings = .f.
oString = .null.
PROCEDURE Init
LPARAMETERS nYear, nMonth, nDay, nHour, nMinute, nSecond
* Messing around with allowing you to set a value for this class and then you can manipulate it.
* Like dtToday = create("DateTime")
* Then you could do stuff like
* dtToday.Date = date()
* ? dtToday.FirstDayOfMonth()
* ? dtToday.Add(45)
IF PCOUNT() > 0
ENDIF
PROCEDURE Day_Access
RETURN DAY(This.Date)
PROCEDURE DayOfWeek_Access
RETURN DOW(This.Date)
PROCEDURE DayOfYear_Access
PROCEDURE Hour_Access
PROCEDURE Kind_Access
PROCEDURE Millisecond_Access
PROCEDURE Minute_Access
PROCEDURE Month_Access
PROCEDURE Second_Access
PROCEDURE Ticks_Access
PROCEDURE TimeOfDay_Access
PROCEDURE Today_Access
PROCEDURE UtcNow_Access
RETURN this.getUTCTime()
PROCEDURE Year_Access
PROCEDURE Date_Access
RETURN EVL(This.Date, DATE())
PROCEDURE Now
RETURN DATETIME()
FUNCTION Add
LPARAMETERS cTimeSpan
RETURN { :}
FUNCTION AddDays
LPARAMETERS iDays
RETURN { :}
FUNCTION AddHours
LPARAMETERS nHours
RETURN { :}
FUNCTION AddMilliseconds
LPARAMETERS iMilliseconds
RETURN { :}
FUNCTION AddMinutes
LPARAMETERS iMonths
RETURN { :}
FUNCTION AddSeconds
LPARAMETERS iSeconds
RETURN { :}
FUNCTION AddTicks
LPARAMETERS iTicks
RETURN { :}
FUNCTION AddYears
LPARAMETERS iYears
RETURN { :}
FUNCTION Compare
LPARAMETERS dt1, dt2
RETURN 0
FUNCTION DaysInMonth
LPARAMETERS iMonth, iYear
LOCAL iYear, iReturn, dDate
dDate = This.Date
iYear = EVL(iYear, YEAR(dDate))
iMonth = EVL(iMonth, MONTH(dDate))
iReturn = This.LastDayOfMonth(iYear, iMonth)-This.FirstDayOfMonth(iYear, iMonth)+1
RETURN iReturn
FUNCTION FirstDayOfMonth(iYear, iMonth)
LOCAL dDate, dReturn
* Thanks Ed Leafe et al
dDate = This.Date
IF PCOUNT()=0
dReturn = dDate-DAY(dDate)+1
ELSE
dReturn = DATE(iYear, iMonth, 1)
ENDIF
RETURN dReturn
FUNCTION LastDayOfMonth(xYear, iMonth)
LOCAL dReturn, dDate
dDate = This.Date
* Thanks Ed Leafe et al
IF PCOUNT()=1
iMonth = MONTH(dDate)
ENDIF
DO CASE
CASE PCOUNT()=0
dReturn = GOMONTH(dDate, 1) - day(dDate)
CASE VARTYPE(xYear)='N'
dReturn = GOMONTH(DATE(xYear, iMonth,1),+1)-1
CASE VARTYPE(xYear)$'DT'
dReturn = GOMONTH(xYear, 1) - day(xYear)
ENDCASE
RETURN dReturn
FUNCTION Equals
LPARAMETERS dtValue
RETURN .f.
FUNCTION GetDateTimeFormats
LPARAMETERS aResult, cTypes
cTypes = EVL(cTypes,"dDfFgGmorstTuUy")
DIMENSION aResult[LEN(cTypes),2]
LOCAL i, cType
FOR i = 1 TO LEN(cTypes)
cType = SUBSTR(cTypes,i,1)
aResult[i,2]=cType
aResult[i,1]=This.ToString(cType)
NEXT
RETURN aResult
FUNCTION GetType
RETURN This.Class
FUNCTION IsDaylightSavingTime()
RETURN This.lDaylightSavings
FUNCTION IsLeapYear
LPARAMETERS iYear
* Thanks, wOOdy
iYear = EVL(iYear, YEAR(This.Date))
RETURN NOT EMPTY(DATE(iYear,2,29))
FUNCTION Parse
LPARAMETERS cDateTime
RETURN { :}
FUNCTION Subtract
LPARAMETERS xTime && Either timespan or datetime
LOCAL tResult
tResult = This.Value
DO CASE
CASE VARTYPE(xTime)='T'
CASE VARTYPE(xTime)='D'
CASE VARTYPE(xTime)='I' && Minutes?
tResult = tResult - xTime
OTHERWISE && Parse TimeSpan
ENDCASE
RETURN tResult
FUNCTION ToLocalTime
LPARAMETERS iUTCOffset
LOCAL ltTime
iUTCOffset=EVL(iUTCOffset,0)
* Returns local time from UTC Time
IF iUTCOffset=0
tReturn = This.FromUtcTime(This.Value)
ELSE
tReturn = This.Subtract((This.iTimeZoneOffset-iUTFOffset)*60)
ENDIF
RETURN tReturn
ENDFUNC
FUNCTION ToLongDateString
RETURN This.ToString('D')
FUNCTION ToLongTimeString
RETURN This.ToString('T')
FUNCTION ToShortDateString
RETURN This.ToString('d')
FUNCTION ToShortTimeString
RETURN This.ToString('t')
FUNCTION ToString
LPARAMETERS cFormat
cFormat=EVL(cFormat,'G')
LOCAL cString
cString = This.oString.Format("{0:"+cFormat+"}", This.Value)
RETURN cString
FUNCTION ToUniversalTime
RETURN { :}
FUNCTION TryParse
LPARAMETERS cString
RETURN .f.
FUNCTION TryParseExact
LPARAMETERS cString
RETURN .f.
************************************************************************
* GetUtcTime
****************************************
*** Function: Returns UTC time from local time
*** Assume:
*** Pass:
*** Return:
************************************************************************
FUNCTION GetUtcTime(ltTime)
ltTime = EVL(ltTime, EVL(This.Value, DATETIME()))
*** Adjust the timezone offset
RETURN ltTime + (This.iTimeZoneOffset * 60)
ENDFUNC
* GetUtcTime
FUNCTION FromUtcTime(ltTime)
* Returns local time from UTC Time
ltTime = EVL(ltTime, This.Value)
RETURN ltTime - (This.iTimeZoneOffset * 60)
ENDFUNC
FUNCTION iTimeZoneOffset_Access
** Returns the TimeZone offset from GMT including daylight savings. Result is returned in minutes.
*** Cache the timezone so this is fast
IF ISNULL(This.iTimeZoneOffset)
LOCAL lcTZ, lnOffset
DECLARE integer GetTimeZoneInformation IN Win32API ;
STRING @ TimeZoneStruct
lcTZ = SPACE(256)
This.lDaylightSavings = (GetTimeZoneInformation(@lcTZ)=2)
lnOffset = This.CharToBin(SUBSTR(lcTZ,1,4),.T.)
This.cTimeZone = SUBSTR(STRCONV(lcTZ, 6),IIF(This.lDaylightSavings,45,3),33)
*** Subtract an hour if daylight savings is active
IF This.lDaylightSavings
lnOffset = lnOffset - 60
ENDIF
This.iTimeZoneOffset = lnOffset
ENDIF
RETURN This.iTimeZoneOffset
PROTECTED FUNCTION CharToBin(lcBinString,llSigned)
****************************************
*** Function: Binary Numeric conversion routine.
*** Converts DWORD or Unsigned Integer string
*** to Fox numeric integer value.
*** Pass: lcBinString - String that contains the binary data
*** llSigned - if .T. uses signed conversion
*** otherwise value is unsigned (DWORD)
*** Return: Fox number
************************************************************************
LOCAL m.i, lnWord
lnWord = 0
FOR m.i = 1 TO LEN(lcBinString)
lnWord = lnWord + (ASC(SUBSTR(lcBinString, m.i, 1)) * (2 ^ (8 * (m.i - 1))))
ENDFOR
IF llSigned AND lnWord > 0x80000000
lnWord = lnWord - 1 - 0xFFFFFFFF
ENDIF
RETURN lnWord
FUNCTION TimeToUnix
LPARAMETERS tcDateTime
tcDateTime=EVL(tcDateTime, This.Value)
tcDateTime=EVL(tcDateTime, This.Now)
RETURN tcDateTime - STARTOFTIME
FUNCTION UnixToTime
LPARAMETERS tnUnixTime
tnUnixTime = EVL(tnUnixTime,0)
RETURN STARTOFTIME + tnUnixTime
FUNCTION oString_Access
IF ISNULL(This.oString)
IF ATC("String",SET("PROC"))=0
SET PROCEDURE TO String ADDITIVE
ENDIF
This.oString=CREATEOBJECT("String")
ENDIF
RETURN this.oString
PROTECTED FUNCTION Value_Access
IF EMPTY(This.Value)
This.Value=DATETIME()
ENDIF
RETURN This.Value
PROTECTED FUNCTION Value_Assign
LPARAMETERS dtValue
LOCAL cType
cType = VARTYPE(dtValue)
IF cType $ 'DT'
This.Value=dtValue
ENDIF
ENDDEFINE