COVERAGE SUMMARY
FILE SUMMARY
NameExecutedRoutines%ExecutedLines%Unexecuted
/home/matt/eu/rds/include/std/datetime.e2929100.00%28831790.85%29
ROUTINE SUMMARY
RoutineExecutedLinesUnexecuted
julianDate()132161.90%8
add()303488.24%4
format()707494.59%4
julianDayOfYear()121675.00%4
julianDay()81172.73%3
parse()464993.88%3
daysInMonth()5683.33%1
daysInYear()3475.00%1
isLeap()5683.33%1
datetime()2121100.00%0
datetimeToSeconds()22100.00%0
days_in_month()22100.00%0
days_in_year()22100.00%0
diff()22100.00%0
from_date()22100.00%0
from_unix()22100.00%0
gmtime()1212100.00%0
is_leap_year()22100.00%0
new()55100.00%0
new_time()22100.00%0
now()22100.00%0
now_gmt()33100.00%0
secondsToDateTime()88100.00%0
subtract()22100.00%0
time()33100.00%0
to_unix()22100.00%0
tolower()22100.00%0
weeks_day()22100.00%0
years_day()22100.00%0
LINE COVERAGE DETAIL
#Executed
1
-- (c) Copyright - See License.txt
2
--
3
--****
4
-- == Date/Time
5
--
6
-- <>
7
8
--
9
namespace datetime
10
11
12
include std/machine.e
13
include std/dll.e
14
include std/sequence.e
15
include std/get.e
16
include std/error.e
17
include std/types.e
18
19101
ifdef LINUX then
20101
constant gmtime_ = define_c_func(open_dll(""), "gmtime", {C_POINTER}, C_POINTER)
21101
constant time_ = define_c_func(open_dll(""), "time", {C_POINTER}, C_INT)
22
elsifdef FREEBSD or SUNOS or OPENBSD then
23
constant gmtime_ = define_c_func(open_dll("libc.so"), "gmtime", {C_POINTER}, C_POINTER)
24
constant time_ = define_c_func(open_dll("libc.so"), "time", {C_POINTER}, C_INT)
25
elsifdef OSX then
26
constant gmtime_ = define_c_func(open_dll("libc.dylib"), "gmtime", {C_POINTER}, C_POINTER)
27
constant time_ = define_c_func(open_dll("libc.dylib"), "time", {C_POINTER}, C_INT)
28
elsifdef WIN32 then
29
constant gmtime_ = define_c_func(open_dll("msvcrt.dll"), "gmtime", {C_POINTER}, C_POINTER)
30
constant time_ = define_c_proc(open_dll("kernel32.dll"), "GetSystemTimeAsFileTime", {C_POINTER})
31
end ifdef
32
33101
enum TM_SEC, TM_MIN, TM_HOUR, TM_MDAY, TM_MON, TM_YEAR --, TM_WDAY, TM_YDAY, TM_ISDST
34
355
365
ifdef WIN32 then
37
atom ptra, valhi, vallow, deltahi, deltalow
38
deltahi = 27111902
39
deltalow = 3577643008
40
ptra = allocate(8)
41
c_proc(time_, {ptra})
42
vallow = peek4u(ptra)
43
valhi = peek4u(ptra+4)
44
free(ptra)
45
vallow -= deltalow
46
valhi -= deltahi
47
if vallow < 0 then
48
vallow += power(2, 32)
49
valhi -= 1
50
end if
51
return floor(((valhi * power(2,32)) + vallow) / 10000000)
52
elsedef
535
return c_func(time_, {NULL})
54
end ifdef
55
end function
56
575
58
sequence ret
59
atom timep, tm_p
60
integer n
61
625
timep = allocate(4)
635
poke4(timep, time)
64
655
tm_p = c_func(gmtime_, {timep})
66
675
free(timep)
68
695
ret = repeat(0, 9)
705
n = 0
71
725
for i = 1 to 9 do
7345
ret[i] = peek4s(tm_p+n)
7445
n = n + 4
7545
end for
76
775
return ret
78
end function
79
80
constant
81101
Gregorian_Reformation = 1752,
82101
Gregorian_Reformation00 = 1700,
83101
DaysPerMonth = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
84101
EPOCH_1970 = 62135856000,
85101
DayLengthInSeconds = 86400
86
87
-- Helpers ------------------------------------------------------------------
88
8924
9024
return x + (x >= 'A' and x <= 'Z') * ('a' - 'A')
91
end function
92
93
-- Date Handling ------------------------------------------------------------
94
9589
96
sequence ly
97
9889
ly = (remainder(year, {4, 100, 400, 3200, 80000})=0)
99
10089
if not ly[1] then return 0 end if
101
10271
if year <= Gregorian_Reformation then
1030
return 1 -- ly[1] can't possibly be 0 here so set shortcut as '1'.
104
else
10571
return ly[1] - ly[2] + ly[3] - ly[4] + ly[5]
106
end if
107
end function
108
109481
110481
if year = Gregorian_Reformation and month = 9 then
1110
return 19
112481
elsif month != 2 then
113406
return DaysPerMonth[month]
114
else
11575
return DaysPerMonth[month] + isLeap(year)
116
end if
117
end function
118
11910
12010
if year = Gregorian_Reformation then
1210
return 355
122
end if
12310
return 365 + isLeap(year)
124
end function
125
126
-- Functions using the new data-types
127
12844
129
integer year, month, day
130
integer d
131
13244
year = ymd[1]
13344
month = ymd[2]
13444
day = ymd[3]
135
13644
if month = 1 then return day end if
137
13835
d = 0
13935
for i = 1 to month - 1 do
140107
d += daysInMonth(year, i)
141107
end for
142
14335
d += day
144
14535
if year = Gregorian_Reformation and month = 9 then
1460
if day > 13 then
1470
d -= 11
1480
elsif day > 2 then
1490
return 0
150
end if
151
end if
152
15335
return d
154
end function
155
15641
157
integer year
158
integer j, greg00
159
16041
year = ymd[1]
16141
j = julianDayOfYear(ymd)
162
16341
year -= 1
16441
greg00 = year - Gregorian_Reformation00
165
16641
j += (
167
365 * year
168
+ floor(year/4)
169
+ (greg00 > 0)
170
* (
171
- floor(greg00/100)
172
+ floor(greg00/400+.25)
173
)
174
- 11 * (year >= Gregorian_Reformation)
175
)
176
17741
if year >= 3200 then
1780
j -= floor(year/ 3200)
1790
if year >= 80000 then
1800
j += floor(year/80000)
181
end if
182
end if
183
18441
return j
185
end function
186
1878
188
integer year, doy
189
190
-- Take a guesstimate at the year -- this is usually v.close
1918
if j >= 0 then
1928
year = floor(j / (12 * 30.43687604)) + 1
193
else
1940
year = -floor(-j / 365.25) + 1
195
end if
196
197
-- Calculate the day in the guessed year
1988
doy = j - (julianDay({year, 1, 1}) - 1) -- = j - last day of prev year
199
200
-- Correct any errors
201
202
-- The guesstimate is usually so close that these whiles could probably
203
-- be made into ifs, but I haven't checked all possible dates yet... ;)
204
2058
while doy <= 0 do -- we guessed too high for the year
2060
year -= 1
2070
doy += daysInYear(year)
2080
end while
209
2108
while doy > daysInYear(year) do -- we guessed too low
2110
doy -= daysInYear(year)
2120
year += 1
2130
end while
214
215
-- guess month
2168
if doy <= daysInMonth(year, 1) then
2171
return {year, 1, doy}
218
end if
2197
for month = 2 to 12 do
22024
doy -= daysInMonth(year, month-1)
22124
if doy <= daysInMonth(year, month) then
2227
return {year, month, doy}
223
end if
22417
end for
225
226
-- Skip to the next year on overflow
227
-- The alternative is a crash, listed below
2280
return {year+1, 1, doy-31}
229
end function
230
231
-- Conversions to and from seconds
232
23311
23411
return julianDay(dt) * DayLengthInSeconds + (dt[4] * 60 + dt[5]) * 60 + dt[6]
235
end function
236
2378
238
integer days, minutes, hours
239
2408
days = floor(seconds / DayLengthInSeconds)
2418
seconds = remainder(seconds, DayLengthInSeconds)
242
2438
hours = floor( seconds / 3600 )
2448
seconds -= hours * 3600
245
2468
minutes = floor( seconds / 60 )
2478
seconds -= minutes* 60
2488
return julianDate(days) & {hours, minutes, seconds}
249
end function
250
251
--****
252
-- === Localized Variables
253
254
--**
255
-- Names of the months
256
257101
public sequence month_names = { "January", "February", "March",
258
"April", "May", "June",
259
"July", "August", "September",
260
"October", "November", "December" }
261
262
--**
263
-- Abbreviations of month names
264
265101
public sequence month_abbrs = { "Jan", "Feb", "Mar",
266
"Apr", "May", "Jun",
267
"Jul", "Aug", "Sep",
268
"Oct", "Nov", "Dec" }
269
270
--**
271
-- Names of the days
272
273101
public sequence day_names = { "Sunday", "Monday",
274
"Tuesday", "Wednesday",
275
"Thursday", "Friday",
276
"Saturday" }
277
278
--**
279
-- Abbreviations of day names
280
281101
public sequence day_abbrs = { "Sun", "Mon",
282
"Tue", "Wed",
283
"Thu", "Fri",
284
"Sat" }
285
286
--**
287
-- AM/PM
288
289101
public sequence ampm = { "AM", "PM" }
290
291
--****
292
-- === Constants
293
--
294
295
--**
296
-- Accessors
297
-- * ##YEAR##
298
-- * ##MONTH##
299
-- * ##DAY##
300
-- * ##HOUR##
301
-- * ##MINUTE##
302
-- * ##SECOND##
303
304101
public enum YEAR, MONTH, DAY, HOUR, MINUTE, SECOND
305
306
--**
307
-- Intervals
308
-- * ##YEARS##
309
-- * ##MONTHS##
310
-- * ##WEEKS##
311
-- * ##DAYS##
312
-- * ##HOURS##
313
-- * ##MINUTES##
314
-- * ##SECONDS##
315
-- * ##DATE##
316
317101
public enum YEARS, MONTHS, WEEKS, DAYS, HOURS, MINUTES, SECONDS, DATE
318
319
--****
320
-- === Types
321
322
--**
323
-- datetime type
324
--
325
-- Parameters:
326
-- # ##obj## : any object, so no crash takes place.
327
--
328
-- Comments:
329
-- A datetime type consists of a sequence of length 6 in the form
330
-- ##{year, month, day_of_month, hour, minute, second}##. Checks are made to guarantee
331
-- those values are in range.
332
--
333
-- Note:
334
-- All components must be integers except
335
-- seconds, as those can also be floating point values.
336
337306
338306
if atom(o) then return 0 end if
339
340306
if length(o) != 6 then return 0 end if
341
342306
if not integer(o[YEAR]) then return 0 end if
343
344306
if not integer(o[MONTH]) then return 0 end if
345
346306
if not integer(o[DAY]) then return 0 end if
347
348306
if not integer(o[HOUR]) then return 0 end if
349
350306
if not integer(o[MINUTE]) then return 0 end if
351
352306
if not atom(o[SECOND]) then return 0 end if
353
354306
if not equal(o[1..3], {0,0,0}) then
355
-- Special case of all zeros is allowed; used when the data is a time only.
356303
if o[MONTH] < 1 then return 0 end if
357
358303
if o[MONTH] > 12 then return 0 end if
359
360303
if o[DAY] < 1 then return 0 end if
361
362303
if o[DAY] > daysInMonth(o[YEAR],o[MONTH]) then return 0 end if
363
end if
364
365306
if o[HOUR] < 0 then return 0 end if
366
367306
if o[HOUR] > 23 then return 0 end if
368
369306
if o[MINUTE] < 0 then return 0 end if
370
371306
if o[MINUTE] > 59 then return 0 end if
372
373306
if o[SECOND] < 0 then return 0 end if
374
375306
if o[SECOND] >= 60 then return 0 end if
376
377306
return 1
378
end type
379
380
--****
381
-- === Routines
382
383
--****
384
-- Signature:
385
-- function time()
386
--
387
-- Description:
388
-- Return the number of seconds since some fixed point in the past.
389
--
390
-- Returns:
391
-- An **atom**, which represents an absolute number of seconds.
392
--
393
-- Comments:
394
-- Take the difference between two readings of ##time##(), to measure, for example, how long
395
-- a section of code takes to execute.
396
--
397
-- On some machines, ##time##() can return a negative number. However, you can still use the
398
-- difference in calls to ##time##() to measure elapsed time.
399
--
400
-- Example 1:
401
--
402
-- constant ITERATIONS = 1000000
403
-- integer p
404
-- atom t0, loop_overhead
405
--
406
-- t0 = time()
407
-- for i = 1 to ITERATIONS do
408
-- -- time an empty loop
409
-- end for
410
-- loop_overhead = time() - t0
411
--
412
-- t0 = time()
413
-- for i = 1 to ITERATIONS do
414
-- p = power(2, 20)
415
-- end for
416
-- ? (time() - t0 - loop_overhead)/ITERATIONS
417
-- -- calculates time (in seconds) for one call to power
418
--
419
--
420
-- See Also:
421
-- [[:date]], [[:now]]
422
423
--****
424
-- Signature:
425
-- function date()
426
--
427
-- Description:
428
-- Return a sequence with information on the current date.
429
--
430
-- Returns:
431
-- A **sequence** of length 8, laid out as follows:
432
-- # year ~-- since 1900
433
-- # month ~-- January = 1
434
-- # day ~-- day of month, starting at 1
435
-- # hour ~-- 0 to 23
436
-- # minute ~-- 0 to 59
437
-- # second ~-- 0 to 59
438
-- # day of the week ~-- Sunday = 1
439
-- # day of the year ~-- January 1st = 1
440
--
441
-- Comments:
442
-- The value returned for the year is actually the number of years since 1900 (not the last 2 digits of the year).
443
-- In the year 2000 this value was 100. In 2001 it was 101, etc.
444
--
445
-- Example 1:
446
--
447
--
448
-- now = date()
449
-- -- now has: {95,3,24,23,47,38,6,83}
450
-- -- i.e. Friday March 24, 1995 at 11:47:38pm, day 83 of the year
451
--
452
--
453
-- See Also:
454
-- [[:time]], [[:now]]
455
456
--**
457
-- Convert a sequence formatted according to the built-in ##date##() function to a valid datetime
458
-- sequence.
459
--
460
-- Parameters:
461
-- # ##src## : a sequence which date() might have returned
462
--
463
-- Returns:
464
-- A **sequence**, more precisely a **datetime** corresponding to the same moment in time.
465
--
466
-- Example 1:
467
--
468
-- d = from_date(date())
469
-- -- d is the current date and time
470
--
471
--
472
-- See Also:
473
-- [[:date]], [[:from_unix]], [[:now]], [[:new]]
474
4755
4765
return {src[YEAR]+1900, src[MONTH], src[DAY], src[HOUR], src[MINUTE], src[SECOND]}
477
end function
478
479
--**
480
-- Create a new datetime value initialized with the current date and time
481
--
482
-- Returns:
483
-- A **sequence**, more precisely a **datetime** corresponding to the current moment in time.
484
--
485
-- Example 1:
486
--
487
-- dt = now()
488
-- -- dt is the current date and time
489
--
490
--
491
-- See Also:
492
-- [[:from_date]], [[:from_unix]], [[:new]], [[:new_time]], [[:now_gmt]]
493
4944
4954
return from_date(date())
496
end function
497
498
--**
499
-- Create a new datetime value that falls into the Greenwich Mean Time (GMT) timezone.
500
-- This function will return a datetime that is GMT, no matter what timezone the system
501
-- is running under.
502
--
503
-- Example 1:
504
--
505
-- dt = now_gmt()
506
-- -- If local time was July 16th, 2008 at 10:34pm CST
507
-- -- dt would be July 17th, 2008 at 03:34pm GMT
508
--
509
--
510
-- See Also:
511
-- [[:now]]
512
5135
5145
sequence t1 = gmtime(time())
515
5165
return {t1[TM_YEAR]+1900, t1[TM_MON]+1, t1[TM_MDAY], t1[TM_HOUR], t1[TM_MIN], t1[TM_SEC]}
517
end function
518
519
--**
520
-- Create a new datetime value.
521
--
522
-- !! TODO: test default parameter usage
523
--
524
-- Parameters:
525
-- # ##year## ~-- the full year.
526
-- # ##month## ~-- the month (1-12).
527
-- # ##day## ~-- the day of the month (1-31).
528
-- # ##hour## ~-- the hour (0-23) (defaults to 0)
529
-- # ##minute## ~-- the minute (0-59) (defaults to 0)
530
-- # ##second## ~-- the second (0-59) (defaults to 0)
531
--
532
-- Example 1:
533
--
534
-- dt = new(2010, 1, 1, 0, 0, 0)
535
-- -- dt is Jan 1st, 2010
536
--
537
--
538
-- See Also:
539
-- [[:from_date]], [[:from_unix]], [[:now]], [[:new_time]]
540
54113
542
integer hour=0, integer minute=0, atom second=0)
543
datetime d
54413
d = {year, month, day, hour, minute, second}
54513
if equal(d, {0,0,0,0,0,0}) then
5461
return now()
547
else
54812
return d
549
end if
550
end function
551
552
--**
553
-- Create a new datetime value with a date of zeros.
554
--
555
-- !! TODO: test
556
--
557
-- Parameters:
558
-- # ##hour## : is the hour (0-23)
559
-- # ##minute## : is the minute (0-59)
560
-- # ##second## : is the second (0-59)
561
--
562
-- Example 1:
563
--
564
-- dt = new_time(10, 30, 55)
565
-- dt is 10:30:55 AM
566
--
567
--
568
-- See Also:
569
-- [[:from_date]], [[:from_unix]], [[:now]], [[:new]]
570
5711
5721
return new(0, 0, 0, hour, minute, second)
573
end function
574
575
--**
576
-- Get the day of week of the datetime dt.
577
--
578
-- Parameters:
579
-- # ##dt## : a datetime to be queried.
580
--
581
-- Returns:
582
-- An **integer**, between 1 (Sunday) and 7 (Saturday).
583
--
584
-- Example 1:
585
--
586
-- d = new(2008, 5, 2, 0, 0, 0)
587
-- day = weeks_day(d) -- day is 6 because May 2, 2008 is a Friday.
588
--
589
59022
59122
return remainder(julianDay(dt)-1+4094, 7) + 1
592
end function
593
594
--**
595
-- Get the Julian day of year of the supplied date.
596
--
597
-- Parameters:
598
-- # ##dt## : a datetime to be queried.
599
--
600
-- Returns:
601
-- An **integer**, between 1 and 366.
602
--
603
-- Comments:
604
-- For dates earlier than 1800, this routine may give inaccurate results if the date
605
-- applies to a country other than United Kingdom or a former colony thereof. The change from
606
-- Julian to Gregorian calendar took place much earlier in some other European countries.
607
--
608
-- Example 1:
609
--
610
-- d = new(2008, 5, 2, 0, 0, 0)
611
-- day = years_day(d) -- day is 123
612
--
613
6142
6152
return julianDayOfYear({dt[YEAR], dt[MONTH], dt[DAY]})
616
end function
617
618
--**
619
-- Determine if ##dt## falls within leap year.
620
--
621
-- Parameters:
622
-- # ##dt## : a datetime to be queried.
623
--
624
-- Returns:
625
-- An **integer**, of 1 if leap year, otherwise 0.
626
--
627
-- Example 1:
628
--
629
-- d = new(2008, 1, 1, 0, 0, 0)
630
-- ? is_leap_year(d) -- prints 1
631
-- d = new(2005, 1, 1, 0, 0, 0)
632
-- ? is_leap_year(d) -- prints 0
633
--
634
--
635
-- See Also:
636
-- [[:days_in_month]]
637
6382
6392
return isLeap(dt[YEAR])
640
end function
641
642
--**
643
-- Return the number of days in the month of ##dt##.
644
--
645
-- This takes into account leap year.
646
--
647
-- Parameters:
648
-- # ##dt## : a datetime to be queried.
649
--
650
-- Example 1:
651
--
652
-- d = new(2008, 1, 1, 0, 0, 0)
653
-- ? days_in_month(d) -- 31
654
-- d = new(2008, 2, 1, 0, 0, 0) -- Leap year
655
-- ? days_in_month(d) -- 29
656
--
657
--
658
-- See Also:
659
-- [[:is_leap_year]]
660
66115
66215
return daysInMonth(dt[YEAR], dt[MONTH])
663
end function
664
665
--**
666
-- Return the number of days in the year of ##dt##.
667
--
668
-- This takes into account leap year.
669
--
670
-- Parameters:
671
-- # ##dt## : a datetime to be queried.
672
--
673
-- Example 1:
674
--
675
-- d = new(2007, 1, 1, 0, 0, 0)
676
-- ? days_in_year(d) -- 365
677
-- d = new(2008, 1, 1, 0, 0, 0) -- leap year
678
-- ? days_in_year(d) -- 366
679
--
680
--
681
-- See Also:
682
-- [[:is_leap_year]], [[:days_in_month]]
683
6842
6852
return daysInYear(dt[YEAR])
686
end function
687
688
--**
689
-- Convert a datetime value to the unix numeric format (seconds since ##EPOCH_1970##)
690
--
691
-- Parameters:
692
-- # ##dt## : a datetime to be queried.
693
--
694
-- Returns:
695
-- An **atom**, so this will not overflow during the winter 2038-2039.
696
--
697
--
698
-- Example 1:
699
--
700
-- secs_since_epoch = to_unix(now())
701
-- -- secs_since_epoch is equal to the current seconds since epoch
702
--
703
--
704
-- See Also:
705
-- [[:from_unix]], [[:format]]
706
7073
7083
return datetimeToSeconds(dt) - EPOCH_1970
709
end function
710
711
--**
712
-- Create a datetime value from the unix numeric format (seconds since EPOCH)
713
--
714
-- Parameters:
715
-- # ##unix## : an atom, counting seconds elapsed since EPOCH.
716
--
717
-- Returns:
718
-- A **sequence**, more precisely a **datetime** representing the same moment in time.
719
--
720
-- Example 1:
721
--
722
-- d = from_unix(0)
723
-- -- d is 1970-01-01 00:00:00 (zero seconds since EPOCH)
724
--
725
--
726
-- See Also:
727
-- [[:to_unix]], [[:from_date]], [[:now]], [[:new]]
728
7292
7302
return secondsToDateTime(EPOCH_1970 + unix)
731
end function
732
733
--**
734
-- Format the date according to the format pattern string
735
--
736
-- Parameters:
737
-- # ##d## : a datetime which is to be printed out
738
-- # ##pattern## : a format string, similar to the ones sprintf() uses, but with some Unicode encoding.
739
-- The default is "%Y-%m-%d %H:%M:%S".
740
--
741
-- Returns:
742
-- A **string**, with the date ##d## formatted according to the specification in ##pattern##.
743
--
744
-- Comments:
745
--
746
-- Pattern string can include the following specifiers~:
747
--
748
-- * ##~%%## ~-- a literal %
749
-- * ##%a## ~-- locale's abbreviated weekday name (e.g., Sun)
750
-- * ##%A## ~-- locale's full weekday name (e.g., Sunday)
751
-- * ##%b## ~-- locale's abbreviated month name (e.g., Jan)
752
-- * ##%B## ~-- locale's full month name (e.g., January)
753
-- * ##%C## ~-- century; like %Y, except omit last two digits (e.g., 21)
754
-- * ##%d## ~-- day of month (e.g, 01)
755
-- * ##%H## ~-- hour (00..23)
756
-- * ##%I## ~-- hour (01..12)
757
-- * ##%j## ~-- day of year (001..366)
758
-- * ##%k## ~-- hour ( 0..23)
759
-- * ##%l## ~-- hour ( 1..12)
760
-- * ##%m## ~-- month (01..12)
761
-- * ##%M## ~-- minute (00..59)
762
-- * ##%p## ~-- locale's equivalent of either AM or PM; blank if not known
763
-- * ##%P## ~-- like %p, but lower case
764
-- * ##%s## ~-- seconds since 1970-01-01 00:00:00 UTC
765
-- * ##%S## ~-- second (00..60)
766
-- * ##%u## ~-- day of week (1..7); 1 is Monday
767
-- * ##%w## ~-- day of week (0..6); 0 is Sunday
768
-- * ##%y## ~-- last two digits of year (00..99)
769
-- * ##%Y## ~-- year
770
--
771
-- Example 1:
772
--
773
-- d = new(2008, 5, 2, 12, 58, 32)
774
-- s = format(d, "%Y-%m-%d %H:%M:%S")
775
-- -- s is "2008-05-02 12:58:32"
776
--
777
--
778
-- Example 2:
779
--
780
-- d = new(2008, 5, 2, 12, 58, 32)
781
-- s = format(d, "%A, %B %d '%y %H:%M%p")
782
-- -- s is "Friday, May 2 '08 12:58PM"
783
--
784
--
785
-- See Also:
786
-- [[:to_unix]], [[:parse]]
787
788111
789
integer in_fmt, ch, tmp
790
sequence res
791
792111
in_fmt = 0
793111
res = ""
794
795111
for i = 1 to length(pattern) do
796372
ch = pattern[i]
797
798372
if in_fmt then
799181
in_fmt = 0
800
801181
if ch = '%' then
8021
res &= '%'
803180
elsif ch = 'a' then
8048
res &= day_abbrs[weeks_day(d)]
805172
elsif ch = 'A' then
8068
res &= day_names[weeks_day(d)]
807164
elsif ch = 'b' then
80813
res &= month_abbrs[d[MONTH]]
809151
elsif ch = 'B' then
81013
res &= month_names[d[MONTH]]
811138
elsif ch = 'C' then
8121
res &= sprintf("%02d", d[YEAR] / 100)
813137
elsif ch = 'd' then
8146
res &= sprintf("%02d", d[DAY])
815131
elsif ch = 'H' then
81630
res &= sprintf("%02d", d[HOUR])
817101
elsif ch = 'I' then
81812
tmp = d[HOUR]
81912
if tmp > 12 then
8201
tmp -= 12
82111
elsif tmp = 0 then
8220
tmp = 12
823
end if
82412
res &= sprintf("%02d", tmp)
82589
elsif ch = 'j' then
8261
res &= sprintf("%d", julianDayOfYear(d))
82788
elsif ch = 'k' then
8281
res &= sprintf("%d", d[HOUR])
82987
elsif ch = 'l' then
83012
tmp = d[HOUR]
83112
if tmp > 12 then
83212
tmp -= 12
8330
elsif tmp = 0 then
8340
tmp = 12
835
end if
83612
res &= sprintf("%d", tmp)
83775
elsif ch = 'm' then
8386
res &= sprintf("%02d", d[MONTH])
83969
elsif ch = 'M' then
8406
res &= sprintf("%02d", d[MINUTE])
84163
elsif ch = 'p' then
84223
if d[HOUR] <= 12 then
84311
res &= ampm[1]
844
else
84512
res &= ampm[2]
846
end if
84740
elsif ch = 'P' then
84824
if d[HOUR] <= 12 then
84911
res &= tolower(ampm[1])
850
else
85113
res &= tolower(ampm[2])
852
end if
85316
elsif ch = 's' then
8541
res &= sprintf("%d", to_unix(d))
85515
elsif ch = 'S' then
8566
res &= sprintf("%02d", d[SECOND])
8579
elsif ch = 'u' then
8581
tmp = weeks_day(d)
8591
if tmp = 1 then
8600
res &= "7" -- Sunday
861
else
8621
res &= sprintf("%d", weeks_day(d) - 1)
863
end if
8648
elsif ch = 'w' then
8651
res &= sprintf("%d", weeks_day(d) - 1)
8667
elsif ch = 'y' then
8671
tmp = floor(d[YEAR] / 100)
8681
res &= sprintf("%02d", d[YEAR] - (tmp * 100))
8696
elsif ch = 'Y' then
8706
res &= sprintf("%04d", d[YEAR])
871
else
872
-- TODO: error or just add?
873
end if
874191
elsif ch = '%' then
875181
in_fmt = 1
876
else
87710
res &= ch
878
end if
879372
end for
880111
return res
881
end function
882
883
--**
884
-- Parse a datetime string according to the given format.
885
--
886
-- Parameters:
887
-- # ##val## : string datetime value
888
-- # ##fmt## : datetime format. Default is "%Y-%m-%d %H:%M:%S"
889
--
890
-- Returns:
891
-- A **datetime**, value.
892
--
893
-- Comments:
894
-- Only a subset of the format specification is currently supported:
895
--
896
-- * ##%d## ~-- day of month (e.g, 01)
897
-- * ##%H## ~-- hour (00..23)
898
-- * ##%m## ~-- month (01..12)
899
-- * ##%M## ~-- minute (00..59)
900
-- * ##%S## ~-- second (00..60)
901
-- * ##%Y## ~-- year
902
--
903
-- More format codes will be added in future versions.
904
--
905
-- All non-format characters in the format string are ignored and are not
906
-- matched against the input string.
907
--
908
-- All non-digits in the input string are ignored.
909
--
910
-- Example 1:
911
--
912
-- datetime d = parse("05/01/2009 10:20:30", "%m/%d/%Y %H:%M:%S")
913
--
914
--
915
-- See Also:
916
-- [[:format]]
917
--
918
9196
9206
integer fpos = 1, spos = 1, maxlen, rpos
9216
sequence res = {0,0,0,0,0,0}
922
9236
while fpos <= length(fmt) do
92446
if fmt[fpos] = '%' then
92536
fpos += 1
926
92736
switch fmt[fpos] do
928
case 'Y' then
9296
rpos = 1
9306
maxlen = 4
931
932
case 'm' then
9336
rpos = 2
9346
maxlen = 2
935
936
case 'd' then
9376
rpos = 3
9386
maxlen = 2
939
940
case 'H' then
9416
rpos = 4
9426
maxlen = 2
943
944
case 'M' then
9456
rpos = 5
9466
maxlen = 2
947
948
case 'S' then
9496
rpos = 6
9506
maxlen = 2
951
952
case else
953
-- Ignore any invalid format character.
9540
rpos = 0
955
956
end switch
957
95836
if rpos then
95936
sequence got
96036
integer epos
96136
while spos <= length(val) do
96261
if t_digit(val[spos]) then
96336
exit
964
end if
96525
spos += 1
96625
end while
967
96836
epos = spos + 1
96936
while epos <= length(val) and epos < spos + maxlen do
97046
if not t_digit(val[epos]) then
9715
exit
972
end if
97341
epos += 1
97441
end while
975
97636
got = value(val[spos .. epos-1], , GET_LONG_ANSWER)
97736
if got[1] != GET_SUCCESS then
9780
return -1
979
end if
980
98136
res[rpos] = got[2]
98236
spos = epos
983
end if
984
end if
98546
fpos += 1
986
98746
end while
988
989
-- Ensure that what we got could be a date-time value.
9906
if not datetime(res) then
9910
return -1
992
end if
993
994
-- Ensure no remaining digits in string.
9956
while spos <= length(val) do
9964
if t_digit(val[spos]) then
9972
return -1
998
end if
9992
spos += 1
10002
end while
1001
10024
return new(res[1], res[2], res[3], res[4], res[5], res[6])
1003
end function
1004
1005
--**
1006
-- Add a number of //intervals// to a datetime.
1007
--
1008
-- Parameters:
1009
-- # ##dt## : the base datetime
1010
-- # ##qty## : the number of //intervals// to add. It should be positive.
1011
-- # ##interval## : which kind of interval to add.
1012
--
1013
-- Returns:
1014
-- A **sequence**, more precisely a **datetime** representing the new moment in time.
1015
--
1016
-- Comments:
1017
-- Please see Constants for Date/Time for a reference of valid intervals.
1018
--
1019
-- Do not confuse the item access constants such as YEAR, MONTH, DAY, etc... with the
1020
-- interval constants YEARS, MONTHS, DAYS, etc...
1021
--
1022
-- When adding MONTHS, it is a calendar based addition. For instance, a date of
1023
-- 5/2/2008 with 5 MONTHS added will become 10/2/2008. MONTHS does not compute the number
1024
-- of days per each month and the average number of days per month.
1025
--
1026
-- When adding YEARS, leap year is taken into account. Adding 4 YEARS to a date may result
1027
-- in a different day of month number due to leap year.
1028
--
1029
-- Example 1:
1030
--
1031
-- d2 = add(d1, 35, SECONDS) -- add 35 seconds to d1
1032
-- d2 = add(d1, 7, WEEKS) -- add 7 weeks to d1
1033
-- d2 = add(d1, 19, YEARS) -- add 19 years to d1
1034
--
1035
--
1036
-- See Also:
1037
-- [[:subtract]], [[:diff]]
1038
103911
1040
integer inc
1041
104211
if interval = SECONDS then
104310
elsif interval = MINUTES then
10441
qty *= 60
10459
elsif interval = HOURS then
10461
qty *= 3600
10478
elsif interval = DAYS then
10482
qty *= 86400
10496
elsif interval = WEEKS then
10501
qty *= 604800
10515
elsif interval = MONTHS then
10523
if qty > 0 then
10532
inc = 1
1054
else
10551
inc = -1
10561
qty = -(qty)
1057
end if
1058
10593
for i = 1 to qty do
106026
if inc = 1 and dt[MONTH] = 12 then
10611
dt[MONTH] = 1
10621
dt[YEAR] += 1
106325
elsif inc = -1 and dt[MONTH] = 1 then
10641
dt[MONTH] = 12
10651
dt[YEAR] -= 1
1066
else
106724
dt[MONTH] += inc
1068
end if
106926
end for
1070
10713
return dt
10722
elsif interval = YEARS then
10732
dt[YEAR] += qty
10742
if isLeap(dt[YEAR]) = 0 and dt[MONTH] = 2 and dt[DAY] = 29 then
10750
dt[MONTH] = 3
10760
dt[DAY] = 1
1077
end if
1078
10792
return dt
10800
elsif interval = DATE then
10810
qty = datetimeToSeconds(qty)
1082
end if
1083
10846
return secondsToDateTime(datetimeToSeconds(dt) + qty)
1085
end function
1086
1087
--**
1088
-- Subtract a number of //intervals// to a base datetime.
1089
--
1090
-- Parameters:
1091
-- # ##dt## : the base datetime
1092
-- # ##qty## : the number of //intervals// to subtract. It should be positive.
1093
-- # ##interval## : which kind of interval to subtract.
1094
--
1095
-- Returns:
1096
-- A **sequence**, more precisely a **datetime** representing the new moment
1097
-- in time.
1098
--
1099
-- Comments:
1100
-- Please see Constants for Date/Time for a reference of valid intervals.
1101
--
1102
-- See the function ##add##() for more information on adding and subtracting date
1103
-- intervals
1104
--
1105
-- Example 1:
1106
--
1107
-- dt2 = subtract(dt1, 18, MINUTES) -- subtract 18 minutes from dt1
1108
-- dt2 = subtract(dt1, 7, MONTHS) -- subtract 7 months from dt1
1109
-- dt2 = subtract(dt1, 12, HOURS) -- subtract 12 hours from dt1
1110
--
1111
--
1112
-- See Also:
1113
-- [[:add]], [[:diff]]
1114
11153
11163
return add(dt, -(qty), interval)
1117
end function
1118
1119
--**
1120
-- Compute the difference, in seconds, between two dates.
1121
--
1122
-- Parameters:
1123
-- # ##dt1## : the end datetime
1124
-- # ##dt2## : the start datetime
1125
--
1126
-- Returns:
1127
-- An **atom**, the number of seconds elapsed from ##dt2## to ##dt1##.
1128
--
1129
-- Comments:
1130
-- ##dt2## is subtracted from ##dt1##, therefore, you can come up with a negative value.
1131
--
1132
-- Example 1:
1133
--
1134
-- d1 = now()
1135
-- sleep(15) -- sleep for 15 seconds
1136
-- d2 = now()
1137
--
1138
-- i = diff(d1, d2) -- i is 15
1139
--
1140
--
1141
-- See Also:
1142
-- [[:add]], [[:subtract]]
1143
11441
11451
return datetimeToSeconds(dt2) - datetimeToSeconds(dt1)
1146
end function