@@ -98,10 +98,12 @@ public final class SystemLibrary: NativeLibrary {
98
98
self . define ( Procedure ( " jiffies-per-second " , self . jiffiesPerSecond) )
99
99
self . define ( Procedure ( " time-zone " , self . timeZone) )
100
100
self . define ( Procedure ( " seconds-from-gmt " , self . secondsFromGmt) )
101
+ self . define ( Procedure ( " date-time " , self . dateTime) )
101
102
self . define ( Procedure ( " seconds->date-time " , self . secondsToDateTime) )
102
103
self . define ( Procedure ( " date-time->seconds " , self . dateTimeToSeconds) )
103
104
self . define ( Procedure ( " date-time->string " , self . dateTimeToString) )
104
105
self . define ( Procedure ( " string->date-time " , self . stringToDateTime) )
106
+ self . define ( Procedure ( " week-number->seconds " , self . weekNumberToSeconds) )
105
107
self . define ( Procedure ( " features " , self . features) )
106
108
self . define ( Procedure ( " implementation-name " , self . implementationName) )
107
109
self . define ( Procedure ( " implementation-version " , self . implementationVersion) )
@@ -567,6 +569,17 @@ public final class SystemLibrary: NativeLibrary {
567
569
return . fixnum( Int64 ( tzone. secondsFromGMT ( ) ) )
568
570
}
569
571
572
+ private func dateTime( args: Arguments ) throws -> Expr {
573
+ var spec = Expr . null
574
+ for arg in args. reversed ( ) {
575
+ spec = . pair( arg, spec)
576
+ }
577
+ guard let ( date, tzone) = self . getDate ( spec, TimeZone . current) else {
578
+ throw RuntimeError . eval ( . invalidDateTime, spec)
579
+ }
580
+ return self . getDateComponents ( date, tzone)
581
+ }
582
+
570
583
private func secondsToDateTime( _ seconds: Expr , _ timeZone: Expr ? ) throws -> Expr {
571
584
guard let tzone = self . getTimeZone ( timeZone) else {
572
585
throw RuntimeError . eval ( . invalidTimeZone, timeZone ?? . false )
@@ -635,6 +648,32 @@ public final class SystemLibrary: NativeLibrary {
635
648
return self . getDateComponents ( date, tzone)
636
649
}
637
650
651
+ private func weekNumberToSeconds( _ year: Expr ,
652
+ _ weekNumber: Expr ,
653
+ _ weekDay: Expr ? ,
654
+ _ timeZone: Expr ? ) throws -> Expr {
655
+ let yr = try year. asInt ( )
656
+ let wnum = try weekNumber. asInt ( )
657
+ guard case . fixnum( let wday) = weekDay ?? . fixnum( 1 ) else {
658
+ throw RuntimeError . type ( weekDay!, expected: [ . exactIntegerType] )
659
+ }
660
+ guard wday >= 1 && wday <= 7 else {
661
+ throw RuntimeError . range ( . fixnum( wday) , min: 1 , max: 7 )
662
+ }
663
+ guard let tzone = self . getTimeZone ( timeZone) else {
664
+ throw RuntimeError . eval ( . invalidTimeZone, timeZone ?? . false )
665
+ }
666
+ guard let date = Calendar . current. date ( from: DateComponents ( calendar: Calendar . current,
667
+ timeZone: tzone,
668
+ year: yr,
669
+ weekday: Int ( wday) ,
670
+ weekOfYear: wnum) ) else {
671
+ throw RuntimeError . eval ( . invalidDateTime,
672
+ . pair( year, . pair( weekNumber, . pair( . fixnum( wday) , . null) ) ) )
673
+ }
674
+ return . makeNumber( date. timeIntervalSince1970)
675
+ }
676
+
638
677
private func getDateComponents( _ date: Date , _ tz: TimeZone ) -> Expr {
639
678
let dc = Calendar . current. dateComponents ( in: tz, from: date)
640
679
let dstOffset = tz. daylightSavingTimeOffset ( for: date)
0 commit comments