@@ -98,10 +98,12 @@ public final class SystemLibrary: NativeLibrary {
9898 self . define ( Procedure ( " jiffies-per-second " , self . jiffiesPerSecond) )
9999 self . define ( Procedure ( " time-zone " , self . timeZone) )
100100 self . define ( Procedure ( " seconds-from-gmt " , self . secondsFromGmt) )
101+ self . define ( Procedure ( " date-time " , self . dateTime) )
101102 self . define ( Procedure ( " seconds->date-time " , self . secondsToDateTime) )
102103 self . define ( Procedure ( " date-time->seconds " , self . dateTimeToSeconds) )
103104 self . define ( Procedure ( " date-time->string " , self . dateTimeToString) )
104105 self . define ( Procedure ( " string->date-time " , self . stringToDateTime) )
106+ self . define ( Procedure ( " week-number->seconds " , self . weekNumberToSeconds) )
105107 self . define ( Procedure ( " features " , self . features) )
106108 self . define ( Procedure ( " implementation-name " , self . implementationName) )
107109 self . define ( Procedure ( " implementation-version " , self . implementationVersion) )
@@ -567,6 +569,17 @@ public final class SystemLibrary: NativeLibrary {
567569 return . fixnum( Int64 ( tzone. secondsFromGMT ( ) ) )
568570 }
569571
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+
570583 private func secondsToDateTime( _ seconds: Expr , _ timeZone: Expr ? ) throws -> Expr {
571584 guard let tzone = self . getTimeZone ( timeZone) else {
572585 throw RuntimeError . eval ( . invalidTimeZone, timeZone ?? . false )
@@ -635,6 +648,32 @@ public final class SystemLibrary: NativeLibrary {
635648 return self . getDateComponents ( date, tzone)
636649 }
637650
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+
638677 private func getDateComponents( _ date: Date , _ tz: TimeZone ) -> Expr {
639678 let dc = Calendar . current. dateComponents ( in: tz, from: date)
640679 let dstOffset = tz. daylightSavingTimeOffset ( for: date)
0 commit comments