Skip to content

Commit b2764cd

Browse files
committed
Implement date-time and week-number->seconds functions of library (lispkit system).
1 parent f96240c commit b2764cd

File tree

1 file changed

+39
-0
lines changed

1 file changed

+39
-0
lines changed

Sources/LispKit/Primitives/SystemLibrary.swift

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)