1 //-------------------------------------------------------------------------
\r
3 // This file contains some DataFlex 3.2 Console Mode functions
\r
4 // to provide extended timestamp and timezone manipulation capabilities.
\r
5 // Depends on functions in both win32.inc and string.inc/
\r
7 // This file is to be included in df32func.mk
\r
9 // Copyright (c) 2006-2015, glyn@8kb.co.uk
\r
11 // df32func/tstamp.inc
\r
12 //-------------------------------------------------------------------------
\r
14 //-------------------------------------------------------------------------
\r
15 // Global tokenizer used for splitting timezon data
\r
16 //-------------------------------------------------------------------------
\r
17 object tzTok is a StringTokenizer
\r
20 //-------------------------------------------------------------------------
\r
22 //-------------------------------------------------------------------------
\r
24 // Convert a textual timestamp to a posix number
\r
25 // Also see posixtime and posixtime_reverse in date.inc
\r
26 function timestemp_to_posix global string inTs returns number
\r
27 local number l_posix l_hr l_min l_sec l_msec
\r
30 // leap seconds not coded
\r
31 if ((length(inTs) < 10) or (mid(inTs, 1, 3) <> "/") or (mid(inTs, 1, 6) <> "/") or (mid(inTs, 1, 11) <> " ")) begin
\r
32 custom_error ERROR_CODE_INVALID_TIMESTAMP$ ERROR_MSG_INVALID_TIMESTAMP ERROR_DETAIL_INVALID_TIMESTAMP "DD/MM/YYYY"
\r
34 if (((length(inTs) >= 16) and (mid(inTs, 1, 14) <> ":")) or ((length(inTs) >= 19) and (mid(inTs, 1, 17) <> ":"));
\r
35 or ((length(inTs) >= 21) and (mid(inTs, 1, 20) <> "."))) begin
\r
36 custom_error ERROR_CODE_INVALID_TIMESTAMP$ ERROR_MSG_INVALID_TIMESTAMP ERROR_DETAIL_INVALID_TIMESTAMP "DD/MM/YYYY HH:mm:SS.mss"
\r
39 move (left(inTs,(pos(" ",inTs)-1))) to l_date
\r
40 if (length(inTs) >= 13) move (mid(inTs, 2, 12)) to l_hr
\r
42 if (length(inTs) >= 16) move (mid(inTs, 2, 15)) to l_min
\r
43 else move 0 to l_min
\r
44 if (length(inTs) >= 19) move (mid(inTs, 2, 18)) to l_sec
\r
45 else move 0 to l_sec
\r
46 if (length(inTs) >= 21) move (mid(inTs, 3, 21)) to l_msec
\r
47 else move 0 to l_msec
\r
49 if ((l_hr > 23) or (l_min > 59) or (l_sec > 59) or (l_msec > 999);
\r
50 or (l_hr < 0) or (l_min < 0) or (l_sec < 0) or (l_msec < 0)) begin
\r
51 custom_error ERROR_CODE_INVALID_TIMESTAMP$ ERROR_MSG_INVALID_TIMESTAMP
\r
54 calc (((integer(l_date))-(integer(date("01/01/1970"))))*86400) to l_posix
\r
55 calc (((((l_hr*60)+l_min)*60)+l_sec)+(l_msec/1000)+l_posix) to l_posix
\r
57 function_return l_posix
\r
60 // Convert a posix number to a textual timestamp
\r
61 function posix_to_timestamp global number argv returns string
\r
63 local number l_subt
\r
64 local integer l_hr l_min l_sec l_msec
\r
65 local string l_posix_reverse
\r
67 // leap seconds not coded
\r
68 calc ((argv/86400)+(integer(date("01/01/1970")))) to l_date
\r
69 calc (argv-(((integer(l_date))-(integer(date("01/01/1970"))))*86400)) to l_subt
\r
70 calc (l_subt/3600) to l_hr
\r
71 calc ((l_subt-(l_hr*3600))/60) to l_min
\r
72 calc (l_subt-(((l_hr*60)+l_min)*60)) to l_sec
\r
73 calc ((l_subt-((((l_hr*60)+l_min)*60)+l_sec))*1000) to l_msec
\r
75 if ((l_hr > 23) or (l_min > 59) or (l_sec > 59) or (l_msec > 999);
\r
76 or (l_hr < 0) or (l_min < 0) or (l_sec < 0) or (l_msec < 0)) begin
\r
77 custom_error ERROR_CODE_INVALID_POSIX_NUMBER$ ERROR_MSG_INVALID_POSIX_NUMBER argv
\r
80 move "" to l_posix_reverse
\r
81 move (string(l_date)+" "+zeropad(l_hr,2)+":"+zeropad(l_min,2)+":"+zeropad(l_sec,2)+"."+zeropad(l_msec,3)) to l_posix_reverse
\r
83 function_return l_posix_reverse
\r
86 // Adjust supplied timestamp by supplied milliseconds
\r
87 function timestamp_adjust global string inTs number inMSeconds returns string
\r
88 local string retTimestamp
\r
91 move (timestemp_to_posix(inTs)) to nPosix
\r
92 move (posix_to_timestamp(nPosix+(inMSeconds/1000))) to retTimestamp
\r
94 function_return retTimestamp
\r
97 // Limited as we'd need to know the actual timestamp referred to to do months, years etc.
\r
98 // Supports millisecond, second, minute, hour, day, week
\r
99 function interval_to_posix global string argv returns number
\r
100 local number l_value l_return
\r
102 local string l_unit l_interval l_numerics
\r
104 move (trim(argv)) to l_interval
\r
107 if (length(l_interval) <> 0) begin
\r
109 while (l_i < length(l_interval))
\r
111 move "" to l_numerics
\r
113 while ((ascii(mid(l_interval, 1, l_i)) > 47) and (ascii(mid(l_interval, 1, l_i)) < 58))
\r
114 append l_numerics (mid(l_interval, 1, l_i))
\r
117 while (ascii(mid(l_interval, 1, l_i)) = 32)
\r
121 while ((ascii(mid(l_interval, 1, l_i)) > 64) and (ascii(mid(l_interval, 1, l_i)) < 91);
\r
122 or (ascii(mid(l_interval, 1, l_i)) > 96) and (ascii(mid(l_interval, 1, l_i)) < 123))
\r
123 append l_unit (mid(l_interval, 1, l_i))
\r
127 move (lowercase(trim(l_unit))) to l_unit
\r
129 case ((mid(l_unit,11,1) = "millisecond") or (mid(l_unit,2,1) = "ms")) move (l_numerics/number(1000)) to l_value
\r
131 case ((mid(l_unit,6,1) = "second") or (mid(l_unit,1,1) = "s")) move l_numerics to l_value
\r
133 case ((mid(l_unit,6,1) = "minute") or (mid(l_unit,1,1) = "m")) move (l_numerics*60) to l_value
\r
135 case ((mid(l_unit,4,1) = "hour") or (mid(l_unit,1,1) = "h")) move (l_numerics*3600) to l_value
\r
137 case ((mid(l_unit,3,1) = "day") or (mid(l_unit,1,1) = "d")) move (l_numerics*86400) to l_value
\r
139 case ((mid(l_unit,4,1) = "week") or (mid(l_unit,1,1) = "w")) move (l_numerics*604800) to l_value
\r
143 move (l_return+l_value) to l_return
\r
147 function_return l_return
\r
150 // Adjust supplied timestamp by supplied interval
\r
151 // Supports microsecond, millisecond, second, minute, hour, day, week, month, year, decade, century, millennium
\r
152 // Negative sinage is indicated by "ago", words without preceeding units are treated as noise. E.g:
\r
153 // timestamp_adjust_interval("28/02/2009 09:00:00.000", "1century 2years 1month 1day 1hour 1minute 1second and 500 milliseconds ago")
\r
154 // Note that actual timestamps will be bound by posix and dataflex timestamp implementations.
\r
155 function timestamp_adjust_interval global string inTs string inInterval returns string
\r
156 local string retTimestamp tmpTimestamp l_unit l_interval l_numerics
\r
157 local number nPosix l_value l_return l_year l_mon l_day
\r
158 local integer l_i l_iThrow l_iSign
\r
160 if ((length(inTs) < 10) or (mid(inTs, 1, 3) <> "/") or (mid(inTs, 1, 6) <> "/")) begin
\r
161 custom_error ERROR_CODE_INVALID_TIMESTAMP$ ERROR_MSG_INVALID_TIMESTAMP ERROR_DETAIL_INVALID_TIMESTAMP "DD/MM/YYYY"
\r
164 move (mid(inTs, 2, 1)) to l_day
\r
165 move (mid(inTs, 2, 4)) to l_mon
\r
166 move (mid(inTs, 4, 7)) to l_year
\r
168 if (lowercase(inInterval) contains "ago");
\r
173 move (trim(inInterval)) to l_interval
\r
176 if (length(l_interval) <> 0) begin
\r
178 while (l_i < length(l_interval))
\r
180 move "" to l_numerics
\r
182 while ((ascii(mid(l_interval, 1, l_i)) > 47) and (ascii(mid(l_interval, 1, l_i)) < 58))
\r
183 append l_numerics (mid(l_interval, 1, l_i))
\r
186 while (ascii(mid(l_interval, 1, l_i)) = 32)
\r
189 while ((ascii(mid(l_interval, 1, l_i)) > 64) and (ascii(mid(l_interval, 1, l_i)) < 91);
\r
190 or (ascii(mid(l_interval, 1, l_i)) > 96) and (ascii(mid(l_interval, 1, l_i)) < 123))
\r
191 append l_unit (mid(l_interval, 1, l_i))
\r
194 move (lowercase(trim(l_unit))) to l_unit
\r
196 case ((mid(l_unit,10,1) = "millennium") or (mid(l_unit,6,1) = "millen")) move (l_year+(l_numerics*1000*l_iSign)) to l_year
\r
198 case ((mid(l_unit,7,1) = "century") or (mid(l_unit,1,1) = "c")) move (l_year+(l_numerics*100*l_iSign)) to l_year
\r
200 case ((mid(l_unit,6,1) = "decade") or (mid(l_unit,3,1) = "dec")) move (l_year+(l_numerics*10*l_iSign)) to l_year
\r
202 case ((mid(l_unit,4,1) = "year") or (mid(l_unit,1,1) = "y")) move (l_year+(l_numerics*l_iSign)) to l_year
\r
204 case ((mid(l_unit,5,1) = "month") or (mid(l_unit,3,1) = "mon")) move (l_mon+(l_numerics*l_iSign)) to l_mon
\r
206 case ((mid(l_unit,11,1) = "millisecond") or (mid(l_unit,2,1) = "ms")) move (l_numerics/number(1000)) to l_value
\r
208 case ((mid(l_unit,6,1) = "second") or (mid(l_unit,1,1) = "s")) move l_numerics to l_value
\r
210 case ((mid(l_unit,6,1) = "minute") or (mid(l_unit,3,1) = "min")) move (l_numerics*60) to l_value
\r
212 case ((mid(l_unit,4,1) = "hour") or (mid(l_unit,1,1) = "h")) move (l_numerics*3600) to l_value
\r
214 case ((mid(l_unit,3,1) = "day") or (mid(l_unit,1,1) = "d")) move (l_numerics*86400) to l_value
\r
216 case ((mid(l_unit,4,1) = "week") or (mid(l_unit,1,1) = "w")) move (l_numerics*604800) to l_value
\r
219 move (l_return+l_value) to l_return
\r
223 move (timestemp_to_posix(zeropad(l_day,2)+"/"+zeropad(l_mon,2)+"/"+zeropad(l_year,4)+mid(inTs,length(inTs)-10,11))) to nPosix
\r
224 move (posix_to_timestamp(nPosix+(l_return*l_iSign))) to retTimestamp
\r
226 function_return retTimestamp
\r
229 // This takes the day of the week and month occourance values from a SYSTEMTIME
\r
230 // in a _TIME_ZONE_INFORMATION and works out the correct day of the month
\r
231 // See description under "DaylightDate" here https://msdn.microsoft.com/en-us/library/ms724253.aspx
\r
232 function get_day_of_month_for_daylight_savings global integer inYear integer inMonth integer inDayOfWeek integer inDay returns integer
\r
233 local integer l_dom l_i
\r
236 if (inDayOfWeek = 0) move 7 to inDayOfWeek
\r
238 move ("01/"+zeropad(inMonth,2)+"/"+zeropad(inYear,4)) to l_date
\r
240 while (get_day_score(l_date) <> inDayOfWeek)
\r
244 if (integer(mid(l_date, 2, 4)) = inMonth);
\r
245 move (mid(l_date, 2, 1)) to l_dom
\r
247 for l_i from 1 to (inDay-1)
\r
248 calc (l_date+7) to l_date
\r
250 if (integer(mid(l_date, 2, 4)) = inMonth);
\r
251 move (mid(l_date, 2, 1)) to l_dom
\r
254 function_return l_dom
\r
257 // Get local system time and starts to pull values to adjust to UTC (needs finishing)
\r
258 function systemtime_utc global returns string
\r
259 local string sSystemTime sTimeZoneInformation sStdName sDlName sFormattedTime sFormattedDate sTs
\r
260 local integer iSuccess iBias iStdBias iDlBias iBiasNow iLenCcTime iLenCcDate iDataLength
\r
261 local pointer lpSystemTime lpTimeZoneInformation lpsFormattedTime lpsFormattedDate
\r
263 // Get the current system local time
\r
264 zerotype _SYSTEMTIME to sSystemTime
\r
265 getaddress of sSystemTime to lpSystemTime
\r
267 move (GetSystemTime(lpSystemTime)) to iSuccess
\r
269 if (iSuccess <> 0) begin
\r
270 // Get the current system timezone information
\r
271 zerotype _TIME_ZONE_INFORMATION to sTimeZoneInformation
\r
272 getaddress of sTimeZoneInformation to lpTimeZoneInformation
\r
274 move (GetTimeZoneInformation(lpTimeZoneInformation)) to iSuccess
\r
276 if (iSuccess = TIME_ZONE_ID_INVALID) begin
\r
277 custom_error ERROR_CODE_INVALID_SYSTEM_TIMEZONE$ ERROR_MSG_INVALID_SYSTEM_TIMEZONE
\r
280 getbuff from sTimeZoneInformation at TIME_ZONE_INFORMATION.Bias to iBias
\r
281 move (cstring(to_ascii(mid(sTimeZoneInformation, 64, 5)))) to sStdName //getbuff from sTimeZoneInformation at TIME_ZONE_INFORMATION.StandardName to sStdName //UTF-16/wchar
\r
282 getbuff from sTimeZoneInformation at TIME_ZONE_INFORMATION.StandardBias to iStdBias
\r
283 move (cstring(to_ascii(mid(sTimeZoneInformation, 64, 89)))) to sDlName //getbuff from sTimeZoneInformation at TIME_ZONE_INFORMATION.DaylightName to sDlName //UTF-16/wcharsDlName
\r
284 getbuff from sTimeZoneInformation at TIME_ZONE_INFORMATION.DaylightBias to iDlBias
\r
286 zerostring 255 to sFormattedTime
\r
287 getaddress of sFormattedTime to lpsFormattedTime
\r
288 move (length(sFormattedTime)) to iLenCcTime
\r
289 move (GetTimeFormat("LOCALE_USER_DEFAULT", 0, lpSystemTime, 0, lpsFormattedTime, iLenCcTime)) to iDataLength
\r
291 zerostring 255 To sFormattedDate
\r
292 getaddress of sFormattedDate To lpsFormattedDate
\r
293 move (length(sFormattedDate)) to iLenCcDate
\r
294 move (GetDateFormat("LOCALE_USER_DEFAULT", 0, lpSystemTime, 0, lpsFormattedDate, iLenCcDate)) to iDataLength
\r
296 // Work out bias and apply to get UTC
\r
297 if (iSuccess = TIME_ZONE_ID_DAYLIGHT) begin
\r
298 move (iBias+iDlBias) to iBiasNow
\r
301 move (iBias+iStdBias) to iBiasNow
\r
304 move (cstring(sFormattedDate) * cstring(sFormattedTime)) to sTs
\r
305 move (timestamp_adjust(sTs, iBiasNow*60000)) to sTs
\r
309 function_return sTs
\r
312 // Returns UTC BIAS in minutes
\r
313 function get_bias global string inDestTz integer inYear integer inMon integer inDay integer inHr integer inMin integer inSec integer inIsUTC returns integer
\r
314 local string sTimeZone sResult sBuf sDaylightDate sDaylightTime sStandardDate sStandardTime StdTs DltTs inTs
\r
315 local integer iSuccess iBiasNow iBias iStdBias iDaylightBias iIsDaylightSaving iThrow iTmp
\r
316 local integer iEYear iEMon iEDay iEDOW iEHr iEMin iESec iBYear iBMon iBDay iBDOW iBHr iBMin iBSec iEDOM iBDOM
\r
317 local number nTO nBO nEO StdPo DltPo inPo
\r
318 local pointer lpTimeZone lpResult
\r
320 ASSERT ((inIsUTC >= 0) and (inIsUTC <= 1)) "Unsupported mode, inIsUTC must be either 1 or 0"
\r
322 move 0 to iIsDaylightSaving
\r
323 move (trim(inDestTz)) to sTimeZone
\r
325 if (sTimeZone <> "") begin
\r
326 if (show_debug_lines = 1);
\r
327 showln "Timezone: " sTimeZone
\r
329 getaddress of sTimeZone to lpTimeZone
\r
331 zerostring 128 to sResult
\r
332 getaddress of sResult to lpResult
\r
334 move (GetTzi(lpTimeZone, lpResult)) to iSuccess
\r
336 if (iSuccess = -1) begin
\r
338 send set_string to (tzTok(current_object)) sResult ","
\r
339 get token_value of (tzTok(current_object)) item 0 to iBias
\r
340 get token_value of (tzTok(current_object)) item 1 to iStdBias
\r
341 get token_value of (tzTok(current_object)) item 2 to iDaylightBias
\r
342 get token_value of (tzTok(current_object)) item 3 to sStandardDate
\r
343 get token_value of (tzTok(current_object)) item 4 to sStandardTime
\r
344 get token_value of (tzTok(current_object)) item 5 to sDaylightDate
\r
345 get token_value of (tzTok(current_object)) item 6 to sDaylightTime
\r
347 // Once all of our data has been retrieved we need to determine daylight saving time
\r
348 //showln sDaylightDate " " sDaylightTime " = " sStandardDate " " sStandardTime
\r
350 send set_string to (tzTok(current_object)) sDaylightDate "/"
\r
351 get token_value of (tzTok(current_object)) item 0 to iBYear
\r
352 get token_value of (tzTok(current_object)) item 1 to iBMon
\r
353 get token_value of (tzTok(current_object)) item 2 to iBDay
\r
354 get token_value of (tzTok(current_object)) item 3 to iBDOW
\r
356 send set_string to (tzTok(current_object)) sStandardDate "/"
\r
357 get token_value of (tzTok(current_object)) item 0 to iEYear
\r
358 get token_value of (tzTok(current_object)) item 1 to iEMon
\r
359 get token_value of (tzTok(current_object)) item 2 to iEDay
\r
360 get token_value of (tzTok(current_object)) item 3 to iEDOW
\r
362 ASSERT ((iBMon <> 0) and (iEMon <> 0)) "Daylight saving not supported"
\r
364 if (show_debug_lines = 1) begin
\r
365 if ((iBMon = 0) or (iEMon = 0));
\r
366 showln "Supports Dls: no"
\r
368 showln "Supports Dls: yes"
\r
371 if ((iBMon <> 0) and (iEMon <> 0)) begin
\r
372 if ((iBYear = 0) or (iBYear = inYear)) begin
\r
374 move (get_day_of_month_for_daylight_savings((iBYear max inYear),iBMon,iBDOW,iBday)) to iBDOM
\r
375 move (get_day_of_month_for_daylight_savings((iEYear max inYear),iEMon,iEDOW,iEday)) to iEDOM
\r
377 send set_string to (tzTok(current_object)) sDaylightTime ":"
\r
378 get token_value of (tzTok(current_object)) item 0 to iBHr
\r
379 get token_value of (tzTok(current_object)) item 1 to iBMin
\r
380 get token_value of (tzTok(current_object)) item 2 to iBSec
\r
382 send set_string to (tzTok(current_object)) sStandardTime ":"
\r
383 get token_value of (tzTok(current_object)) item 0 to iEHr
\r
384 get token_value of (tzTok(current_object)) item 1 to iEMin
\r
385 get token_value of (tzTok(current_object)) item 2 to iESec
\r
387 move (zeropad(iBDOM,2)+"/"+zeropad(iBMon,2)+"/"+string(iEYear max inYear)+" "+zeropad(iBHr,2)+":"+zeropad(iBMin,2)+":"+zeropad(iBSec,2)) to DltTs
\r
388 move (zeropad(iEDOM,2)+"/"+zeropad(iEMon,2)+"/"+string(iEYear max inYear)+" "+zeropad(iEHr,2)+":"+zeropad(iEMin,2)+":"+zeropad(iESec,2)) to StdTs
\r
389 move (zeropad(inDay,2)+"/"+zeropad(inMon,2)+"/"+string(inYear)+" "+zeropad(inHr,2)+":"+zeropad(inMin,2)+":"+zeropad(inSec,2)) to inTs
\r
391 move (timestemp_to_posix(DltTs)) to DltPo
\r
392 move (timestemp_to_posix(StdTs)) to StdPo
\r
393 move (timestemp_to_posix(inTs)+(iBias*-60*inIsUTC)) to inPo
\r
395 if (show_debug_lines = 1) begin
\r
396 showln "InTimestamp: " inTs
\r
397 showln "CmpTimestamp: " (posix_to_timestamp(inPo))
\r
398 showln "DaylightTimestamp: " DltTs " Offset=" (iBias+iDaylightBias)
\r
399 showln "StandardTimestamp: " StdTs " Offset=" (iBias+iStdBias)
\r
402 if (DltPo < StdPo) begin
\r
403 if ((inPo >= DltPo) and (inPo < StdPo)) move 1 to iIsDaylightSaving
\r
406 if not ((inPo >= StdPo) and (inPo < DltPo)) move 1 to iIsDaylightSaving
\r
412 // If the clocks go forward at 1.00am then the 1.00am-1.59am doesn't exist in localtime;
\r
413 // conversins back and forth between nonexistent times will look wrong, but should never occour
\r
414 // If the clocks go back at 1.00am then 1.00am effectively occours twice
\r
415 // More info: http://www.timeanddate.com/time/dst/transition.html
\r
417 // Now we can figure out the actual bias
\r
418 if (iIsDaylightSaving = 1) begin
\r
419 move (iBias+iDaylightBias) to iBiasNow
\r
420 if (show_debug_lines = 1) begin
\r
421 showln "Zone currently in daylight saving"
\r
425 move (iBias+iStdBias) to iBiasNow
\r
427 if (show_debug_lines = 1) begin
\r
428 showln "Bias: " iBiasNow
\r
431 send destroy_object to tzTok
\r
434 custom_error ERROR_CODE_INVALID_TIMESTAMP$ ERROR_MSG_INVALID_TIMESTAMP
\r
438 function_return iBiasNow
\r
441 // Returns UTC time converted from the current time in the passed timezone
\r
442 function get_utc_time_from_timezone_time global string inDestTz string inTs returns string
\r
443 local integer l_bias
\r
445 local integer inGmtYear inGmtMon inGmtDay inGmtHr inGmtMin inGmtSec
\r
447 if ((length(inTs) < 10) or (mid(inTs, 1, 3) <> "/") or (mid(inTs, 1, 6) <> "/") or (mid(inTs, 1, 11) <> " ")) begin
\r
448 custom_error ERROR_CODE_INVALID_TIMESTAMP$ ERROR_MSG_INVALID_TIMESTAMP ERROR_DETAIL_INVALID_TIMESTAMP "DD/MM/YYYY"
\r
450 if (((length(inTs) >= 16) and (mid(inTs, 1, 14) <> ":")) or ((length(inTs) >= 19) and (mid(inTs, 1, 17) <> ":"));
\r
451 or ((length(inTs) >= 21) and (mid(inTs, 1, 20) <> "."))) begin
\r
452 custom_error ERROR_CODE_INVALID_TIMESTAMP$ ERROR_MSG_INVALID_TIMESTAMP ERROR_DETAIL_INVALID_TIMESTAMP "DD/MM/YYYY HH:mm:SS.mss"
\r
455 move (mid(inTs, 2, 1)) to inGmtDay
\r
456 move (mid(inTs, 2, 4)) to inGmtMon
\r
457 move (mid(inTs, 4, 7)) to inGmtyear
\r
459 if (length(inTs) >= 13) move (mid(inTs, 2, 12)) to inGmtHr
\r
460 else move 0 to inGmtHr
\r
461 if (length(inTs) >= 16) move (mid(inTs, 2, 15)) to inGmtMin
\r
462 else move 0 to inGmtMin
\r
463 if (length(inTs) >= 19) move (mid(inTs, 2, 18)) to inGmtSec
\r
464 else move 0 to inGmtSec
\r
466 move (get_bias(inDestTz, inGmtYear, inGmtMon, inGmtDay, inGmtHr, inGmtMin, inGmtSec, 0)) to l_bias
\r
467 move (zeropad(inGmtDay,2)+"/"+zeropad(inGmtMon,2)+"/"+zeropad(inGmtYear,4)+" "+zeropad(inGmtHr,2)+":"+zeropad(inGmtMin,2)+":"+zeropad(inGmtSec,2)) to l_ts
\r
469 move (timestamp_adjust(l_ts, l_bias*60000)) to l_ts
\r
471 function_return l_ts
\r
474 //Returns current time in the passed timezone from the time passed as UTC
\r
475 function get_timezone_time_from_utc_time global string inDestTz string inTs returns string
\r
476 local integer l_bias
\r
478 local integer inUtcYear inUtcMonth inUtcDay inUtcHr inUtcMin inUtcSec
\r
480 if ((length(inTs) < 10) or (mid(inTs, 1, 3) <> "/") or (mid(inTs, 1, 6) <> "/") or (mid(inTs, 1, 11) <> " ")) begin
\r
481 custom_error ERROR_CODE_INVALID_TIMESTAMP$ ERROR_MSG_INVALID_TIMESTAMP ERROR_DETAIL_INVALID_TIMESTAMP "DD/MM/YYYY"
\r
483 if (((length(inTs) >= 16) and (mid(inTs, 1, 14) <> ":")) or ((length(inTs) >= 19) and (mid(inTs, 1, 17) <> ":"));
\r
484 or ((length(inTs) >= 21) and (mid(inTs, 1, 20) <> "."))) begin
\r
485 custom_error ERROR_CODE_INVALID_TIMESTAMP$ ERROR_MSG_INVALID_TIMESTAMP ERROR_DETAIL_INVALID_TIMESTAMP "DD/MM/YYYY HH:mm:SS.mss"
\r
488 move (mid(inTs, 2, 1)) to inUtcDay
\r
489 move (mid(inTs, 2, 4)) to inUtcMonth
\r
490 move (mid(inTs, 4, 7)) to inUtcyear
\r
492 if (length(inTs) >= 13) move (mid(inTs, 2, 12)) to inUtcHr
\r
493 else move 0 to inUtcHr
\r
494 if (length(inTs) >= 16) move (mid(inTs, 2, 15)) to inUtcMin
\r
495 else move 0 to inUtcMin
\r
496 if (length(inTs) >= 19) move (mid(inTs, 2, 18)) to inUtcSec
\r
497 else move 0 to inUtcSec
\r
499 move (get_bias(inDestTz, inUtcYear, inUtcMonth, inUtcDay, inUtcHr, inUtcMin, inUtcSec, 1)) to l_bias
\r
500 move (zeropad(inUtcDay,2)+"/"+zeropad(inUtcMonth,2)+"/"+zeropad(inUtcYear,4)+" "+zeropad(inUtcHr,2)+":"+zeropad(inUtcMin,2)+":"+zeropad(inUtcSec,2)) to l_ts
\r
502 move (timestamp_adjust(l_ts, l_bias*-60000)) to l_ts
\r
504 function_return l_ts
\r
507 //Convert a timestamp from one local zone to another
\r
508 function get_timezone_time_from_timezone_time global string inSourceTz string inDestTz string inTs returns string
\r
511 move (get_timezone_time_from_utc_time(inDestTz, (get_utc_time_from_timezone_time(inSourceTz, inTs)))) to l_ts
\r
513 function_return l_ts
\r