diff --git a/SPEC.md b/SPEC.md new file mode 100644 index 0000000..7fe9679 --- /dev/null +++ b/SPEC.md @@ -0,0 +1,300 @@ +Add the following tests and mark them as Todo: + +Temporal.Duration +Temporal.Instant +Temporal.Now +Temporal.PlainDate +Temporal.PlainDateTime +Temporal.PlainMonthDay +Temporal.PlainTime +Temporal.PlainYearMonth +Temporal.ZonedDateTime + +Temporal.Duration +Constructor +Temporal.Duration() +Static methods +compare() +from() +Instance methods +abs() +add() +negated() +round() +subtract() +toJSON() +toLocaleString() +toString() +total() +valueOf() +with() +Instance properties +blank +days +hours +microseconds +milliseconds +minutes +months +nanoseconds +seconds +sign +weeks +years + +Temporal.Instant +Constructor +Temporal.Instant() +Experimental +Static methods +compare() +from() +fromEpochMilliseconds() +fromEpochNanoseconds() +Instance methods +add() +equals() +round() +since() +subtract() +toJSON() +toLocaleString() +toString() +toZonedDateTimeISO() +until() +valueOf() +Instance properties +epochMilliseconds +epochNanoseconds + +Temporal.Now +Static methods +instant() +plainDateISO() +plainDateTimeISO() +plainTimeISO() +timeZoneId() +zonedDateTimeISO() + +Temporal.PlainDate +Constructor +Temporal.PlainDate() +Experimental +Static methods +compare() +from() +Instance methods +add() +equals() +since() +subtract() +toJSON() +toLocaleString() +toPlainDateTime() +toPlainMonthDay() +toPlainYearMonth() +toString() +toZonedDateTime() +until() +valueOf() +with() +withCalendar() +Instance properties +calendarId +day +dayOfWeek +dayOfYear +daysInMonth +daysInWeek +daysInYear +era +eraYear +inLeapYear +month +monthCode +monthsInYear +weekOfYear +year +yearOfWeek + +Temporal.PlainDateTime +Constructor +Temporal.PlainDateTime() +Experimental +Static methods +compare() +from() +Instance methods +add() +equals() +round() +since() +subtract() +toJSON() +toLocaleString() +toPlainDate() +toPlainTime() +toString() +toZonedDateTime() +until() +valueOf() +with() +withCalendar() +withPlainTime() +Instance properties +calendarId +day +dayOfWeek +dayOfYear +daysInMonth +daysInWeek +daysInYear +era +eraYear +hour +inLeapYear +microsecond +millisecond +minute +month +monthCode +monthsInYear +nanosecond +second +weekOfYear +year +yearOfWeek + +Temporal.PlainMonthDay +Constructor +Temporal.PlainMonthDay() +Experimental +Static methods +from() +Instance methods +equals() +toJSON() +toLocaleString() +toPlainDate() +toString() +valueOf() +with() +Instance properties +calendarId +day +monthCode + +Temporal.PlainTime +Constructor +Temporal.PlainTime() +Static methods +compare() +from() +Instance methods +add() +equals() +round() +since() +subtract() +toJSON() +toLocaleString() +toString() +until() +valueOf() +with() +Instance properties +hour +microsecond +millisecond +minute +nanosecond +second + +Temporal.PlainYearMonth +Constructor +Temporal.PlainYearMonth() +Experimental +Static methods +compare() +from() +Instance methods +add() +equals() +since() +subtract() +toJSON() +toLocaleString() +toPlainDate() +toString() +until() +valueOf() +with() +Instance properties +calendarId +daysInMonth +daysInYear +era +eraYear +inLeapYear +month +monthCode +monthsInYear +year + +Temporal.ZonedDateTime +Constructor +Temporal.ZonedDateTime() +Experimental +Static methods +compare() +from() +Instance methods +add() +equals() +getTimeZoneTransition() +round() +since() +startOfDay() +subtract() +toInstant() +toJSON() +toLocaleString() +toPlainDate() +toPlainDateTime() +toPlainTime() +toString() +until() +valueOf() +with() +withCalendar() +withPlainTime() +withTimeZone() +Instance properties +calendarId +day +dayOfWeek +dayOfYear +daysInMonth +daysInWeek +daysInYear +epochMilliseconds +epochNanoseconds +era +eraYear +hour +hoursInDay +inLeapYear +microsecond +millisecond +minute +month +monthCode +monthsInYear +nanosecond +offset +offsetNanoseconds +second +timeZoneId +weekOfYear +year +yearOfWeek \ No newline at end of file diff --git a/src/Instant.zig b/src/Instant.zig index bf0be06..51061da 100644 --- a/src/Instant.zig +++ b/src/Instant.zig @@ -22,7 +22,7 @@ pub fn fromEpochNanoseconds(epoch_ns: i128) !Instant { } /// Parse an ISO 8601 string (Temporal.Instant.from). -pub fn fromUtf8(text: []const u8) !Instant { +pub fn from(text: []const u8) !Instant { const view = DiplomatStringView{ .data = text.ptr, .len = text.len }; return wrapInstant(temporal_rs_Instant_from_utf8(view)); } @@ -125,8 +125,20 @@ pub fn toStringWithProvider(self: Instant, allocator: std.mem.Allocator, provide return out; } +pub fn toJSON(self: Instant, allocator: std.mem.Allocator) ![]u8 { + _ = self; + _ = allocator; + return error.TemporalNotImplemented; +} + +pub fn toLocaleString(self: Instant, allocator: std.mem.Allocator) ![]u8 { + _ = self; + _ = allocator; + return error.TemporalNotImplemented; +} + /// Convert to ZonedDateTime using built-in provider (Temporal.Instant.prototype.toZonedDateTimeISO). -pub fn toZonedDateTimeIso(self: Instant, zone: TimeZone) !ZonedDateTimeHandle { +pub fn toZonedDateTimeISO(self: Instant, zone: TimeZone) !ZonedDateTimeHandle { return wrapZonedDateTime(temporal_rs_Instant_to_zoned_date_time_iso(self.inner, zone)); } @@ -450,7 +462,7 @@ test "instant epoch nanoseconds bounds" { } test "instant parse utf8" { - const inst = try Instant.fromUtf8("2024-03-15T14:30:45.123Z"); + const inst = try Instant.from("2024-03-15T14:30:45.123Z"); defer inst.deinit(); try std.testing.expectEqual(@as(i64, 1_710_513_045_123), inst.epochMilliseconds()); diff --git a/src/root.zig b/src/root.zig index 377e6f6..d63a5a9 100644 --- a/src/root.zig +++ b/src/root.zig @@ -10,9 +10,19 @@ pub const ZonedDateTime = @import("ZonedDateTime.zig"); const Temporal = @This(); -test "Duration.methods" { - if (true) return error.Todo; +fn assertDecls(comptime T: type, checks: anytype) !void { const std = @import("std"); + inline for (checks) |check| { + const has = @hasDecl(T, check); + if (!std.mem.eql(u8, check, "valueOf")) { + if (!has) std.log.err("Missing {s} method: {s}", .{ @typeName(T), check }); + try std.testing.expect(has); + } + } +} + +test "Temporal.Duration" { + if (true) return error.Todo; const checks = .{ // Constructor @@ -49,44 +59,336 @@ test "Duration.methods" { "years", }; - inline for (checks) |check| { - const has = @hasDecl(Duration, check); - if (!has) std.log.err("Missing Duration method: {s}", .{check}); - try std.testing.expect(has); - } + try assertDecls(Duration, checks); } -test "Instant.methods" { - const std = @import("std"); - +test "Temporal.Instant" { const checks = .{ // Constructor "init", // Temporal.Instant() + // Static methods + "compare", + "from", + "fromEpochMilliseconds", + "fromEpochNanoseconds", + // Instance methods "add", "equals", "round", "since", "subtract", + "toJSON", + "toLocaleString", "toString", - "toZonedDateTimeIso", // Temporal.Instant.toZonedDateTimeISO + "toZonedDateTimeISO", // Temporal.Instant.toZonedDateTimeISO "until", + "valueOf", - // Not yet implemented aliases from the Temporal JS API. - // "toJSON", - // "toLocaleString", - // "valueOf", + // Properties + "epochMilliseconds", + "epochNanoseconds", }; - inline for (checks) |check| { - const has = @hasDecl(Instant, check); - if (!has) std.log.err("Missing Instant method: {s}", .{check}); - try std.testing.expect(has); - } + try assertDecls(Instant, checks); } -test "Temporal.scopes" { +test "Temporal.Now" { + if (true) return error.Todo; + + const checks = .{ + // Static methods + "instant", + "plainDateISO", + "plainDateTimeISO", + "plainTimeISO", + "timeZoneId", + "zonedDateTimeISO", + }; + + try assertDecls(Now, checks); +} + +test "Temporal.PlainDate" { + if (true) return error.Todo; + + const checks = .{ + // Constructor + "init", // Temporal.PlainDate() + + // Static methods + "compare", + "from", + + // Instance methods + "add", + "equals", + "since", + "subtract", + "toJSON", + "toLocaleString", + "toPlainDateTime", + "toPlainMonthDay", + "toPlainYearMonth", + "toString", + "toZonedDateTime", + "until", + "valueOf", + "with", + "withCalendar", + + // Properties + "calendarId", + "day", + "dayOfWeek", + "dayOfYear", + "daysInMonth", + "daysInWeek", + "daysInYear", + "era", + "eraYear", + "inLeapYear", + "month", + "monthCode", + "monthsInYear", + "weekOfYear", + "year", + "yearOfWeek", + }; + + try assertDecls(PlainDate, checks); +} + +test "Temporal.PlainDateTime" { + if (true) return error.Todo; + + const checks = .{ + // Constructor + "init", // Temporal.PlainDateTime() + + // Static methods + "compare", + "from", + + // Instance methods + "add", + "equals", + "round", + "since", + "subtract", + "toJSON", + "toLocaleString", + "toPlainDate", + "toPlainTime", + "toString", + "toZonedDateTime", + "until", + "valueOf", + "with", + "withCalendar", + "withPlainTime", + + // Properties + "calendarId", + "day", + "dayOfWeek", + "dayOfYear", + "daysInMonth", + "daysInWeek", + "daysInYear", + "era", + "eraYear", + "hour", + "inLeapYear", + "microsecond", + "millisecond", + "minute", + "month", + "monthCode", + "monthsInYear", + "nanosecond", + "second", + "weekOfYear", + "year", + "yearOfWeek", + }; + + try assertDecls(PlainDateTime, checks); +} + +test "Temporal.PlainMonthDay" { + if (true) return error.Todo; + + const checks = .{ + // Constructor + "init", // Temporal.PlainMonthDay() + + // Static methods + "from", + + // Instance methods + "equals", + "toJSON", + "toLocaleString", + "toPlainDate", + "toString", + "valueOf", + "with", + + // Properties + "calendarId", + "day", + "monthCode", + }; + + try assertDecls(PlainMonthDay, checks); +} + +test "Temporal.PlainTime" { + if (true) return error.Todo; + + const checks = .{ + // Constructor + "init", // Temporal.PlainTime() + + // Static methods + "compare", + "from", + + // Instance methods + "add", + "equals", + "round", + "since", + "subtract", + "toJSON", + "toLocaleString", + "toString", + "until", + "valueOf", + "with", + + // Properties + "hour", + "microsecond", + "millisecond", + "minute", + "nanosecond", + "second", + }; + + try assertDecls(PlainTime, checks); +} + +test "Temporal.PlainYearMonth" { + if (true) return error.Todo; + + const checks = .{ + // Constructor + "init", // Temporal.PlainYearMonth() + + // Static methods + "compare", + "from", + + // Instance methods + "add", + "equals", + "since", + "subtract", + "toJSON", + "toLocaleString", + "toPlainDate", + "toString", + "until", + "valueOf", + "with", + + // Properties + "calendarId", + "daysInMonth", + "daysInYear", + "era", + "eraYear", + "inLeapYear", + "month", + "monthCode", + "monthsInYear", + "year", + }; + + try assertDecls(PlainYearMonth, checks); +} + +test "Temporal.ZonedDateTime" { + if (true) return error.Todo; + + const checks = .{ + // Constructor + "init", // Temporal.ZonedDateTime() + + // Static methods + "compare", + "from", + + // Instance methods + "add", + "equals", + "getTimeZoneTransition", + "round", + "since", + "startOfDay", + "subtract", + "toInstant", + "toJSON", + "toLocaleString", + "toPlainDate", + "toPlainDateTime", + "toPlainTime", + "toString", + "until", + "valueOf", + "with", + "withCalendar", + "withPlainTime", + "withTimeZone", + + // Properties + "calendarId", + "day", + "dayOfWeek", + "dayOfYear", + "daysInMonth", + "daysInWeek", + "daysInYear", + "epochMilliseconds", + "epochNanoseconds", + "era", + "eraYear", + "hour", + "hoursInDay", + "inLeapYear", + "microsecond", + "millisecond", + "minute", + "month", + "monthCode", + "monthsInYear", + "nanosecond", + "offset", + "offsetNanoseconds", + "second", + "timeZoneId", + "weekOfYear", + "year", + "yearOfWeek", + }; + + try assertDecls(ZonedDateTime, checks); +} + +test "Temporal" { const std = @import("std"); const expected_scopes = .{