diff --git a/src/Duration.zig b/src/Duration.zig index f725fbd..9fafa90 100644 --- a/src/Duration.zig +++ b/src/Duration.zig @@ -1,6 +1,6 @@ const std = @import("std"); const abi = @import("abi.zig"); -const temporal = @import("temporal.zig"); +const t = @import("temporal.zig"); const PlainDate = @import("PlainDate.zig"); const PlainDateTime = @import("PlainDateTime.zig"); @@ -8,11 +8,13 @@ const ZonedDateTime = @import("ZonedDateTime.zig"); const Duration = @This(); -pub const ToStringOptions = temporal.ToStringRoundingOptions; -pub const ToStringRoundingOptions = temporal.ToStringRoundingOptions; -pub const Unit = temporal.Unit; -pub const RoundingMode = temporal.RoundingMode; -pub const Sign = temporal.Sign; +_inner: *abi.c.Duration, + +pub const ToStringOptions = t.ToStringRoundingOptions; +pub const ToStringRoundingOptions = t.ToStringRoundingOptions; +pub const Unit = t.Unit; +pub const RoundingMode = t.RoundingMode; +pub const Sign = t.Sign; pub const RoundingOptions = struct { largest_unit: ?Unit = null, @@ -20,15 +22,6 @@ pub const RoundingOptions = struct { rounding_mode: ?RoundingMode = null, rounding_increment: ?u32 = null, relative_to: ?RelativeTo = null, - - pub fn toCApi(self: RoundingOptions) abi.c.RoundingOptions { - return .{ - .largest_unit = abi.toUnitOption(temporal.toCUnit(self.largest_unit)), - .smallest_unit = abi.toUnitOption(temporal.toCUnit(self.smallest_unit)), - .rounding_mode = abi.toRoundingModeOption(temporal.toCRoundingMode(self.rounding_mode)), - .increment = abi.toOption(abi.c.OptionU32, self.rounding_increment), - }; - } }; /// Partial duration specification for creating Duration objects. @@ -44,31 +37,6 @@ pub const PartialDuration = struct { milliseconds: ?i64 = null, microseconds: ?f64 = null, nanoseconds: ?f64 = null, - - fn toCApi(self: PartialDuration) abi.c.PartialDuration { - return .{ - .years = abi.toOption(abi.c.OptionI64, self.years), - .months = abi.toOption(abi.c.OptionI64, self.months), - .weeks = abi.toOption(abi.c.OptionI64, self.weeks), - .days = abi.toOption(abi.c.OptionI64, self.days), - .hours = abi.toOption(abi.c.OptionI64, self.hours), - .minutes = abi.toOption(abi.c.OptionI64, self.minutes), - .seconds = abi.toOption(abi.c.OptionI64, self.seconds), - .milliseconds = abi.toOption(abi.c.OptionI64, self.milliseconds), - .microseconds = abi.toOption(abi.c.OptionF64, self.microseconds), - .nanoseconds = abi.toOption(abi.c.OptionF64, self.nanoseconds), - }; - } -}; - -/// Wrapper for PlainDate reference in RelativeTo -const PlainDateRef = struct { - _inner: *abi.c.PlainDate, -}; - -/// Wrapper for ZonedDateTime reference in RelativeTo -const ZonedDateTimeRef = struct { - _inner: *abi.c.ZonedDateTime, }; /// Relative-to context for duration operations. @@ -76,14 +44,6 @@ pub const RelativeTo = union(enum) { plain_date: PlainDate, plain_date_time: PlainDateTime, zoned_date_time: ZonedDateTime, - - fn toCApi(self: RelativeTo) abi.c.RelativeTo { - switch (self) { - .plain_date => |pd| return .{ .date = pd._inner }, - .zoned_date_time => |zdt| return .{ .zoned = zdt._inner }, - .plain_date_time => |pdt| return .{ .date = (pdt.toPlainDate() catch unreachable)._inner }, - } - } }; /// Options for Duration.total() providing unit and relative-to context. @@ -96,8 +56,6 @@ pub const CompareOptions = struct { relative_to: ?RelativeTo = null, }; -_inner: *abi.c.Duration, - /// Construct a Duration from years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, and nanoseconds. /// Equivalent to `Temporal.Duration.from()` or the constructor. pub fn init( @@ -176,7 +134,7 @@ inline fn fromUtf8(text: []const u8) !Duration { /// Create a Duration from a partial duration (where some fields may be omitted). fn fromPartialDuration(partial: PartialDuration) !Duration { - return wrapDuration(abi.c.temporal_rs_Duration_from_partial_duration(partial.toCApi())); + return wrapDuration(abi.c.temporal_rs_Duration_from_partial_duration(abi.to.partialdur(partial))); } /// Check if the time portion of the duration is within valid ranges. @@ -236,7 +194,7 @@ pub fn nanoseconds(self: Duration) f64 { /// Get the sign of the duration: positive (1), zero (0), or negative (-1). pub fn sign(self: Duration) Sign { - return Sign.fromCApi(abi.c.temporal_rs_Duration_sign(self._inner)); + return abi.from.sign(abi.c.temporal_rs_Duration_sign(self._inner)); } /// Check if the duration is zero (all fields are zero). @@ -268,8 +226,8 @@ pub fn subtract(self: Duration, other: Duration) !Duration { /// Round the duration according to the specified options (Temporal.Duration.prototype.round). pub fn round(self: Duration, options: RoundingOptions) !Duration { - const rel = if (options.relative_to) |r| r.toCApi() else abi.c.RelativeTo{ .date = null, .zoned = null }; - return wrapDuration(abi.c.temporal_rs_Duration_round(self._inner, options.toCApi(), rel)); + const rel = if (options.relative_to) |r| abi.to.durRelativeTo(r) else abi.c.RelativeTo{ .date = null, .zoned = null }; + return wrapDuration(abi.c.temporal_rs_Duration_round(self._inner, abi.to.durRoundingOpts(options), rel)); } /// Round the duration with an explicit provider. @@ -279,7 +237,7 @@ fn roundWithProvider(self: Duration, options: RoundingOptions, relative_to: Rela /// Compare two durations (Temporal.Duration.compare). pub fn compare(self: Duration, other: Duration, options: CompareOptions) !i8 { - const rel = if (options.relative_to) |r| r.toCApi() else abi.c.RelativeTo{ .date = null, .zoned = null }; + const rel = if (options.relative_to) |r| abi.to.durRelativeTo(r) else abi.c.RelativeTo{ .date = null, .zoned = null }; const res = abi.c.temporal_rs_Duration_compare(self._inner, other._inner, rel); return try abi.extractResult(res); } @@ -292,14 +250,14 @@ fn compareWithProvider(self: Duration, other: Duration, relative_to: RelativeTo, /// Get the total value of the duration in the specified unit (Temporal.Duration.prototype.total). pub fn total(self: Duration, options: TotalOptions) !f64 { - const rel = if (options.relative_to) |r| r.toCApi() else abi.c.RelativeTo{ .date = null, .zoned = null }; - const res = abi.c.temporal_rs_Duration_total(self._inner, options.unit.toCApi(), rel); + const rel = if (options.relative_to) |r| abi.to.durRelativeTo(r) else abi.c.RelativeTo{ .date = null, .zoned = null }; + const res = abi.c.temporal_rs_Duration_total(self._inner, abi.to.unit(options.unit).?, rel); return try abi.extractResult(res); } /// Get the total value of the duration with an explicit provider. fn totalWithProvider(self: Duration, options: TotalOptions, provider: *const abi.c.Provider) !f64 { - const rel = if (options.relative_to) |r| r.toCApi() else abi.c.RelativeTo{ .date = null, .zoned = null }; + const rel = if (options.relative_to) |r| abi.to.durRelativeTo(r) else abi.c.RelativeTo{ .date = null, .zoned = null }; const res = abi.c.temporal_rs_Duration_total_with_provider(self._inner, options.unit.toCApi(), rel, provider); return try abi.extractResult(res); } @@ -309,7 +267,7 @@ pub fn toString(self: Duration, allocator: std.mem.Allocator, options: ToStringR var write = abi.DiplomatWrite.init(allocator); defer write.deinit(); - const res = abi.c.temporal_rs_Duration_to_string(self._inner, options.toCApi(), &write.inner); + const res = abi.c.temporal_rs_Duration_to_string(self._inner, abi.to.strRoundingOpts(options), &write.inner); try handleVoidResult(res); return try write.toOwnedSlice(); @@ -580,15 +538,15 @@ test total { const dur = try Duration.init(0, 0, 0, 0, 1, 30, 0, 0, 0, 0); defer dur.deinit(); - const t = try dur.total(.{ .unit = .hour }); - try std.testing.expectEqual(1.5, t); + const ttl = try dur.total(.{ .unit = .hour }); + try std.testing.expectEqual(1.5, ttl); } { const dur = try Duration.from("PT4H5M6S"); defer dur.deinit(); - const t = try dur.total(.{ .unit = .hour }); - try std.testing.expectEqual(4.085, t); + const ttl = try dur.total(.{ .unit = .hour }); + try std.testing.expectEqual(4.085, ttl); } { diff --git a/src/Instant.zig b/src/Instant.zig index e204f53..e9f7de5 100644 --- a/src/Instant.zig +++ b/src/Instant.zig @@ -1,30 +1,19 @@ const std = @import("std"); const abi = @import("abi.zig"); -const temporal = @import("temporal.zig"); +const t = @import("temporal.zig"); const Duration = @import("Duration.zig"); const Instant = @This(); -pub const Unit = temporal.Unit; -pub const RoundingMode = temporal.RoundingMode; -pub const Sign = temporal.Sign; -pub const RoundingOptions = temporal.RoundingOptions; -pub const DifferenceSettings = temporal.DifferenceSettings; +_inner: *abi.c.Instant, -/// Time zone identifier for Temporal operations -pub const TimeZone = struct { - _inner: abi.c.TimeZone, - - pub fn init(id: []const u8) TimeZone { - const view = abi.toDiplomatStringView(id); - return .{ ._inner = .{ .id = view } }; - } - - fn toCApi(self: TimeZone) abi.c.TimeZone { - return self._inner; - } -}; +pub const Unit = t.Unit; +pub const RoundingMode = t.RoundingMode; +pub const Sign = t.Sign; +pub const RoundingOptions = t.RoundingOptions; +pub const DifferenceSettings = t.DifferenceSettings; +pub const TimeZone = t.TimeZone; /// Options for Instant.toString() /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant/toString @@ -47,8 +36,6 @@ pub const ToStringOptions = struct { time_zone: ?TimeZone = null, }; -_inner: *abi.c.Instant, - /// Construct from epoch nanoseconds (Temporal.Instant.fromEpochNanoseconds). pub fn init(epoch_ns: i128) !Instant { return fromEpochNanoseconds(epoch_ns); @@ -112,19 +99,19 @@ pub fn subtract(self: Instant, duration: *Duration) !Instant { /// Difference until another instant (Temporal.Instant.prototype.until). pub fn until(self: Instant, other: Instant, settings: DifferenceSettings) !Duration { - const ptr = (try abi.extractResult(abi.c.temporal_rs_Instant_until(self._inner, other._inner, settings.toCApi()))) orelse return abi.TemporalError.Generic; + const ptr = (try abi.extractResult(abi.c.temporal_rs_Instant_until(self._inner, other._inner, abi.to.diffsettings(settings)))) orelse return abi.TemporalError.Generic; return .{ ._inner = ptr }; } /// Difference since another instant (Temporal.Instant.prototype.since). pub fn since(self: Instant, other: Instant, settings: DifferenceSettings) !Duration { - const ptr = (try abi.extractResult(abi.c.temporal_rs_Instant_since(self._inner, other._inner, settings.toCApi()))) orelse return abi.TemporalError.Generic; + const ptr = (try abi.extractResult(abi.c.temporal_rs_Instant_since(self._inner, other._inner, abi.to.diffsettings(settings)))) orelse return abi.TemporalError.Generic; return .{ ._inner = ptr }; } /// Round this instant (Temporal.Instant.prototype.round). pub fn round(self: Instant, options: RoundingOptions) !Instant { - return wrapInstant(abi.c.temporal_rs_Instant_round(self._inner, options.toCApi())); + return wrapInstant(abi.c.temporal_rs_Instant_round(self._inner, abi.to.roundingOpts(options))); } /// Compare two instants (Temporal.Instant.compare). @@ -235,8 +222,8 @@ fn optsToRounding(opts: ToStringOptions) abi.c.ToStringRoundingOptions { else defaultPrecision(); - const smallest_unit = if (opts.smallest_unit) |unit| unit.toCApi() else null; - const rounding_mode = if (opts.rounding_mode) |mode| mode.toCApi() else null; + const smallest_unit = if (opts.smallest_unit) |unit| abi.to.unit(unit).? else null; + const rounding_mode = if (opts.rounding_mode) |mode| abi.to.roundingMode(mode) else null; return .{ .precision = precision, diff --git a/src/PlainDate.zig b/src/PlainDate.zig index aeb9b72..b4b500d 100644 --- a/src/PlainDate.zig +++ b/src/PlainDate.zig @@ -1,6 +1,6 @@ const std = @import("std"); const abi = @import("abi.zig"); -const temporal = @import("temporal.zig"); +const t = @import("temporal.zig"); const PlainDateTime = @import("PlainDateTime.zig"); const PlainMonthDay = @import("PlainMonthDay.zig"); @@ -11,10 +11,12 @@ const Duration = @import("Duration.zig"); const PlainDate = @This(); -pub const Unit = temporal.Unit; -pub const RoundingMode = temporal.RoundingMode; -pub const Sign = temporal.Sign; -pub const DifferenceSettings = temporal.DifferenceSettings; +_inner: *abi.c.PlainDate, + +pub const Unit = t.Unit; +pub const RoundingMode = t.RoundingMode; +pub const Sign = t.Sign; +pub const DifferenceSettings = t.DifferenceSettings; pub const ToStringOptions = struct { calendar_id: ?CalendarDisplay = null, @@ -41,8 +43,6 @@ pub const ToZonedDateTimeOptions = struct { plain_time: ?PlainTime = null, }; -_inner: *abi.c.PlainDate, - pub fn init(year_val: i32, month_val: u8, day_val: u8) !PlainDate { return calInit(year_val, month_val, day_val, "iso8601"); } @@ -104,12 +104,12 @@ pub fn subtract(self: PlainDate, duration: Duration) !PlainDate { } pub fn until(self: PlainDate, other: PlainDate, settings: DifferenceSettings) !Duration { - const ptr = (try abi.extractResult(abi.c.temporal_rs_PlainDate_until(self._inner, other._inner, settings.toCApi()))) orelse return abi.TemporalError.Generic; + const ptr = (try abi.extractResult(abi.c.temporal_rs_PlainDate_until(self._inner, other._inner, abi.to.diffsettings(settings)))) orelse return abi.TemporalError.Generic; return .{ ._inner = ptr }; } pub fn since(self: PlainDate, other: PlainDate, settings: DifferenceSettings) !Duration { - const ptr = (try abi.extractResult(abi.c.temporal_rs_PlainDate_since(self._inner, other._inner, settings.toCApi()))) orelse return abi.TemporalError.Generic; + const ptr = (try abi.extractResult(abi.c.temporal_rs_PlainDate_since(self._inner, other._inner, abi.to.diffsettings(settings)))) orelse return abi.TemporalError.Generic; return .{ ._inner = ptr }; } @@ -129,7 +129,7 @@ pub fn withCalendar(self: PlainDate, calendar: []const u8) !PlainDate { } pub fn toPlainDateTime(self: PlainDate, time: ?PlainTime) !PlainDateTime { - const time_ptr = if (time) |t| t._inner else null; + const time_ptr = if (time) |tt| tt._inner else null; const ptr = (try abi.extractResult(abi.c.temporal_rs_PlainDate_to_plain_date_time(self._inner, time_ptr))) orelse return abi.TemporalError.Generic; return .{ ._inner = ptr }; } @@ -149,7 +149,7 @@ pub fn toZonedDateTime(self: PlainDate, options: ToZonedDateTimeOptions) !ZonedD const tz_result = abi.c.temporal_rs_TimeZone_try_from_str(tz_view); const time_zone = try abi.extractResult(tz_result); - const time_ptr = if (options.plain_time) |t| t._inner else null; + const time_ptr = if (options.plain_time) |tt| tt._inner else null; const ptr = (try abi.extractResult(abi.c.temporal_rs_PlainDate_to_zoned_date_time(self._inner, time_zone, time_ptr))) orelse return abi.TemporalError.Generic; return .{ ._inner = ptr }; diff --git a/src/PlainDateTime.zig b/src/PlainDateTime.zig index b6cfb90..97c7e5e 100644 --- a/src/PlainDateTime.zig +++ b/src/PlainDateTime.zig @@ -1,6 +1,6 @@ const std = @import("std"); const abi = @import("abi.zig"); -const temporal = @import("temporal.zig"); +const t = @import("temporal.zig"); const PlainDate = @import("PlainDate.zig"); const PlainTime = @import("PlainTime.zig"); @@ -12,11 +12,11 @@ const PlainDateTime = @This(); _inner: *abi.c.PlainDateTime, // Import types from temporal.zig -pub const Unit = temporal.Unit; -pub const RoundingMode = temporal.RoundingMode; -pub const Sign = temporal.Sign; -pub const DifferenceSettings = temporal.DifferenceSettings; -pub const RoundOptions = temporal.RoundingOptions; +pub const Unit = t.Unit; +pub const RoundingMode = t.RoundingMode; +pub const Sign = t.Sign; +pub const DifferenceSettings = t.DifferenceSettings; +pub const RoundOptions = t.RoundingOptions; // Type definitions for API compatibility pub const CalendarDisplay = enum { auto, @@ -208,20 +208,20 @@ pub fn subtract(self: PlainDateTime, duration: Duration) !PlainDateTime { } pub fn until(self: PlainDateTime, other: PlainDateTime, options: DifferenceSettings) !Duration { - const result = abi.c.temporal_rs_PlainDateTime_until(self._inner, other._inner, options.toCApi()); + const result = abi.c.temporal_rs_PlainDateTime_until(self._inner, other._inner, abi.to.diffsettings(options)); const ptr = (try abi.extractResult(result)) orelse return abi.TemporalError.Generic; return .{ ._inner = ptr }; } pub fn since(self: PlainDateTime, other: PlainDateTime, options: DifferenceSettings) !Duration { - const result = abi.c.temporal_rs_PlainDateTime_since(self._inner, other._inner, options.toCApi()); + const result = abi.c.temporal_rs_PlainDateTime_since(self._inner, other._inner, abi.to.diffsettings(options)); const ptr = (try abi.extractResult(result)) orelse return abi.TemporalError.Generic; return .{ ._inner = ptr }; } // Rounding pub fn round(self: PlainDateTime, options: RoundOptions) !PlainDateTime { - return wrapPlainDateTime(abi.c.temporal_rs_PlainDateTime_round(self._inner, options.toCApi())); + return wrapPlainDateTime(abi.c.temporal_rs_PlainDateTime_round(self._inner, abi.to.roundingOpts(options))); } // Property accessors - Date fields @@ -375,12 +375,12 @@ pub fn withCalendar(self: PlainDateTime, calendar: []const u8) !PlainDateTime { } pub fn withPlainTime(self: PlainDateTime, time: ?PlainTime) !PlainDateTime { - const new_hour: u8 = if (time) |t| t.hour() else 0; - const new_minute: u8 = if (time) |t| t.minute() else 0; - const new_second: u8 = if (time) |t| t.second() else 0; - const new_millisecond: u16 = if (time) |t| t.millisecond() else 0; - const new_microsecond: u16 = if (time) |t| t.microsecond() else 0; - const new_nanosecond: u16 = if (time) |t| t.nanosecond() else 0; + const new_hour: u8 = if (time) |tt| tt.hour() else 0; + const new_minute: u8 = if (time) |tt| tt.minute() else 0; + const new_second: u8 = if (time) |tt| tt.second() else 0; + const new_millisecond: u16 = if (time) |tt| tt.millisecond() else 0; + const new_microsecond: u16 = if (time) |tt| tt.microsecond() else 0; + const new_nanosecond: u16 = if (time) |tt| tt.nanosecond() else 0; const calendar_ptr = abi.c.temporal_rs_PlainDateTime_calendar(self._inner) orelse return error.TemporalError; const cal_id_view = abi.c.temporal_rs_Calendar_identifier(calendar_ptr); @@ -597,10 +597,10 @@ test toPlainDate { test toPlainTime { const dt = try PlainDateTime.init(2024, 1, 15, 14, 30, 45, 0, 0, 0); - const t = try dt.toPlainTime(); - try std.testing.expectEqual(@as(u8, 14), t.hour()); - try std.testing.expectEqual(@as(u8, 30), t.minute()); - try std.testing.expectEqual(@as(u8, 45), t.second()); + const tt = try dt.toPlainTime(); + try std.testing.expectEqual(@as(u8, 14), tt.hour()); + try std.testing.expectEqual(@as(u8, 30), tt.minute()); + try std.testing.expectEqual(@as(u8, 45), tt.second()); } test toZonedDateTime { @@ -635,8 +635,8 @@ test withCalendar { test withPlainTime { const dt = try PlainDateTime.init(2024, 1, 15, 14, 30, 0, 0, 0, 0); - const t = try PlainTime.from("10:15:30"); - const result = try dt.withPlainTime(t); + const tt = try PlainTime.from("10:15:30"); + const result = try dt.withPlainTime(tt); try std.testing.expectEqual(@as(u8, 10), result.hour()); try std.testing.expectEqual(@as(u8, 15), result.minute()); try std.testing.expectEqual(@as(u8, 30), result.second()); diff --git a/src/PlainMonthDay.zig b/src/PlainMonthDay.zig index 7f7e2cc..81f47a4 100644 --- a/src/PlainMonthDay.zig +++ b/src/PlainMonthDay.zig @@ -1,9 +1,10 @@ const std = @import("std"); const abi = @import("abi.zig"); -const temporal_types = @import("temporal.zig"); +const t = @import("temporal.zig"); + +const PlainDate = @import("PlainDate.zig"); const PlainMonthDay = @This(); -const PlainDate = @import("PlainDate.zig"); _inner: *abi.c.PlainMonthDay, diff --git a/src/PlainTime.zig b/src/PlainTime.zig index 53fd966..08e8f29 100644 --- a/src/PlainTime.zig +++ b/src/PlainTime.zig @@ -1,17 +1,18 @@ const std = @import("std"); const abi = @import("abi.zig"); -const temporal_types = @import("temporal.zig"); +const t = @import("temporal.zig"); + +const Duration = @import("Duration.zig"); const PlainTime = @This(); -const Duration = @import("Duration.zig"); _inner: *abi.c.PlainTime, // Import types from temporal.zig -pub const Unit = temporal_types.Unit; -pub const RoundingMode = temporal_types.RoundingMode; -pub const DifferenceSettings = temporal_types.DifferenceSettings; -pub const RoundOptions = temporal_types.RoundingOptions; +pub const Unit = t.Unit; +pub const RoundingMode = t.RoundingMode; +pub const DifferenceSettings = t.DifferenceSettings; +pub const RoundOptions = t.RoundingOptions; pub const WithOptions = struct { hour: ?u8 = null, @@ -81,14 +82,14 @@ pub fn subtract(self: PlainTime, duration: Duration) !PlainTime { } pub fn until(self: PlainTime, other: PlainTime, options: DifferenceSettings) !Duration { - const settings = options.toCApi(); + const settings = abi.to.diffsettings(options); const result = abi.c.temporal_rs_PlainTime_until(self._inner, other._inner, settings); const ptr = (try abi.extractResult(result)) orelse return abi.TemporalError.Generic; return .{ ._inner = ptr }; } pub fn since(self: PlainTime, other: PlainTime, options: DifferenceSettings) !Duration { - const settings = options.toCApi(); + const settings = abi.to.diffsettings(options); const result = abi.c.temporal_rs_PlainTime_since(self._inner, other._inner, settings); const ptr = (try abi.extractResult(result)) orelse return abi.TemporalError.Generic; return .{ ._inner = ptr }; @@ -96,7 +97,7 @@ pub fn since(self: PlainTime, other: PlainTime, options: DifferenceSettings) !Du // Rounding pub fn round(self: PlainTime, options: RoundOptions) !PlainTime { - return wrapPlainTime(abi.c.temporal_rs_PlainTime_round(self._inner, options.toCApi())); + return wrapPlainTime(abi.c.temporal_rs_PlainTime_round(self._inner, abi.to.roundingOpts(options))); } // Property accessors @@ -146,8 +147,8 @@ pub fn toString(self: PlainTime, allocator: std.mem.Allocator) ![]u8 { return toStringWithOptions(self, allocator, .{}); } -fn toStringWithOptions(self: PlainTime, allocator: std.mem.Allocator, options: temporal_types.ToStringRoundingOptions) ![]u8 { - const rounding_opts = options.toCApi(); +fn toStringWithOptions(self: PlainTime, allocator: std.mem.Allocator, options: t.ToStringRoundingOptions) ![]u8 { + const rounding_opts = abi.to.strRoundingOpts(options); var write = abi.DiplomatWrite.init(allocator); defer write.deinit(); diff --git a/src/PlainYearMonth.zig b/src/PlainYearMonth.zig index fbb0ef4..cb98680 100644 --- a/src/PlainYearMonth.zig +++ b/src/PlainYearMonth.zig @@ -1,18 +1,19 @@ const std = @import("std"); const abi = @import("abi.zig"); -const temporal_types = @import("temporal.zig"); +const t = @import("temporal.zig"); -const PlainYearMonth = @This(); const PlainDate = @import("PlainDate.zig"); const Duration = @import("Duration.zig"); +const PlainYearMonth = @This(); + _inner: *abi.c.PlainYearMonth, // Import types from temporal.zig -pub const Unit = temporal_types.Unit; -pub const RoundingMode = temporal_types.RoundingMode; -pub const DifferenceSettings = temporal_types.DifferenceSettings; -pub const RoundOptions = temporal_types.RoundingOptions; +pub const Unit = t.Unit; +pub const RoundingMode = t.RoundingMode; +pub const DifferenceSettings = t.DifferenceSettings; +pub const RoundOptions = t.RoundingOptions; // Type definitions for API compatibility pub const CalendarDisplay = enum { @@ -95,14 +96,14 @@ pub fn subtract(self: PlainYearMonth, duration: Duration) !PlainYearMonth { } pub fn until(self: PlainYearMonth, other: PlainYearMonth, options: DifferenceSettings) !Duration { - const settings = options.toCApi(); + const settings = abi.to.diffsettings(options); const result = abi.c.temporal_rs_PlainYearMonth_until(self._inner, other._inner, settings); const ptr = (try abi.extractResult(result)) orelse return abi.TemporalError.Generic; return .{ ._inner = ptr }; } pub fn since(self: PlainYearMonth, other: PlainYearMonth, options: DifferenceSettings) !Duration { - const settings = options.toCApi(); + const settings = abi.to.diffsettings(options); const result = abi.c.temporal_rs_PlainYearMonth_since(self._inner, other._inner, settings); const ptr = (try abi.extractResult(result)) orelse return abi.TemporalError.Generic; return .{ ._inner = ptr }; diff --git a/src/ZonedDateTime.zig b/src/ZonedDateTime.zig index 7660efd..c98f912 100644 --- a/src/ZonedDateTime.zig +++ b/src/ZonedDateTime.zig @@ -1,6 +1,6 @@ const std = @import("std"); const abi = @import("abi.zig"); -const temporal_types = @import("temporal.zig"); +const t = @import("temporal.zig"); const Instant = @import("Instant.zig"); const PlainDate = @import("PlainDate.zig"); @@ -13,11 +13,11 @@ const ZonedDateTime = @This(); _inner: *abi.c.ZonedDateTime, // Import types from temporal.zig -pub const Unit = temporal_types.Unit; -pub const RoundingMode = temporal_types.RoundingMode; -pub const Sign = temporal_types.Sign; -pub const DifferenceSettings = temporal_types.DifferenceSettings; -pub const RoundOptions = temporal_types.RoundingOptions; +pub const Unit = t.Unit; +pub const RoundingMode = t.RoundingMode; +pub const Sign = t.Sign; +pub const DifferenceSettings = t.DifferenceSettings; +pub const RoundOptions = t.RoundingOptions; pub const TimeZone = struct { _inner: abi.c.TimeZone, @@ -179,12 +179,12 @@ pub fn getTimeZoneTransition(self: ZonedDateTime, direction: enum { next, previo /// Round to the given options pub fn round(self: ZonedDateTime, options: RoundOptions) !ZonedDateTime { - return wrapZonedDateTime(abi.c.temporal_rs_ZonedDateTime_round(self._inner, options.toCApi())); + return wrapZonedDateTime(abi.c.temporal_rs_ZonedDateTime_round(self._inner, abi.to.roundingOpts(options))); } /// Calculate duration since another ZonedDateTime pub fn since(self: ZonedDateTime, other: ZonedDateTime, settings: DifferenceSettings) !Duration { - const ptr = try abi.extractResult(abi.c.temporal_rs_ZonedDateTime_since(self._inner, other._inner, settings.toCApi())); + const ptr = try abi.extractResult(abi.c.temporal_rs_ZonedDateTime_since(self._inner, other._inner, abi.to.diffsettings(settings))); return .{ ._inner = ptr }; } @@ -253,7 +253,7 @@ pub fn toString(self: ZonedDateTime, allocator: std.mem.Allocator, opts: ToStrin /// Calculate duration until another ZonedDateTime pub fn until(self: ZonedDateTime, other: ZonedDateTime, settings: DifferenceSettings) !Duration { - const ptr = try abi.extractResult(abi.c.temporal_rs_ZonedDateTime_until(self._inner, other._inner, settings.toCApi())); + const ptr = try abi.extractResult(abi.c.temporal_rs_ZonedDateTime_until(self._inner, other._inner, abi.to.diffsettings(settings))); return .{ ._inner = ptr }; } @@ -281,7 +281,7 @@ pub fn withCalendar(self: ZonedDateTime, calendar: []const u8) !ZonedDateTime { /// Create a new ZonedDateTime with a different time pub fn withPlainTime(self: ZonedDateTime, time: ?PlainTime) !ZonedDateTime { - const time_ptr = if (time) |t| t._inner else null; + const time_ptr = if (time) |tt| tt._inner else null; return wrapZonedDateTime(abi.c.temporal_rs_ZonedDateTime_with_plain_time(self._inner, time_ptr)); } diff --git a/src/abi.zig b/src/abi.zig index 6e36d52..cb3a054 100644 --- a/src/abi.zig +++ b/src/abi.zig @@ -304,3 +304,145 @@ pub inline fn extractResult(result: anytype) TemporalError!Success(@TypeOf(resul // Fallback for result types without detailed error information return TemporalError.Generic; } + +const t = @import("temporal.zig"); +const dur = @import("Duration.zig"); +const ins = @import("Instant.zig"); + +pub const to = struct { + pub fn unit(opt: ?t.Unit) ?c.Unit { + return if (opt) |u| @as(c.Unit, @intCast(to.unitToCApi(u))) else null; + } + + fn unitToCApi(u: t.Unit) c_uint { + return switch (u) { + .auto => c.Unit_Auto, + .nanosecond => c.Unit_Nanosecond, + .microsecond => c.Unit_Microsecond, + .millisecond => c.Unit_Millisecond, + .second => c.Unit_Second, + .minute => c.Unit_Minute, + .hour => c.Unit_Hour, + .day => c.Unit_Day, + .week => c.Unit_Week, + .month => c.Unit_Month, + .year => c.Unit_Year, + }; + } + + pub fn roundingMode(opt: ?t.RoundingMode) ?c.RoundingMode { + return if (opt) |m| @as(c.RoundingMode, @intCast(to.roundingModeToCApi(m))) else null; + } + + fn roundingModeToCApi(m: t.RoundingMode) c_uint { + return switch (m) { + .ceil => c.RoundingMode_Ceil, + .floor => c.RoundingMode_Floor, + .expand => c.RoundingMode_Expand, + .trunc => c.RoundingMode_Trunc, + .half_ceil => c.RoundingMode_HalfCeil, + .half_floor => c.RoundingMode_HalfFloor, + .half_expand => c.RoundingMode_HalfExpand, + .half_trunc => c.RoundingMode_HalfTrunc, + .half_even => c.RoundingMode_HalfEven, + }; + } + + pub fn sign(opt: ?t.Sign) ?c.Sign { + return if (opt) |s| @as(c.Sign, @intCast(to.signToCApi(s))) else null; + } + + fn signToCApi(s: t.Sign) c_int { + return switch (s) { + .positive => c.Sign_Positive, + .zero => c.Sign_Zero, + .negative => c.Sign_Negative, + }; + } + + pub fn strRoundingOpts(self: t.ToStringRoundingOptions) c.ToStringRoundingOptions { + const precision: c.Precision = if (self.fractional_second_digits) |fsd| + .{ .is_minute = false, .precision = toOption(c.OptionU8, fsd) } + else if (self.smallest_unit) |su| + switch (su) { + .second => .{ .is_minute = false, .precision = toOption(c.OptionU8, 0) }, + .millisecond => .{ .is_minute = false, .precision = toOption(c.OptionU8, 3) }, + .microsecond => .{ .is_minute = false, .precision = toOption(c.OptionU8, 6) }, + .nanosecond => .{ .is_minute = false, .precision = toOption(c.OptionU8, 9) }, + else => .{ .is_minute = false, .precision = toOption(c.OptionU8, null) }, + } + else + .{ .is_minute = false, .precision = toOption(c.OptionU8, null) }; + + return .{ + .precision = precision, + .smallest_unit = toUnitOption(unit(self.smallest_unit)), + .rounding_mode = toRoundingModeOption(roundingMode(self.rounding_mode)), + }; + } + + pub fn durRoundingOpts(self: dur.RoundingOptions) c.RoundingOptions { + return .{ + .largest_unit = toUnitOption(unit(self.largest_unit)), + .smallest_unit = toUnitOption(unit(self.smallest_unit)), + .rounding_mode = toRoundingModeOption(roundingMode(self.rounding_mode)), + .increment = toOption(c.OptionU32, self.rounding_increment), + }; + } + + pub fn tz(self: ins.TimeZone) c.TimeZone { + return self._inner; + } + + pub fn partialdur(self: dur.PartialDuration) c.PartialDuration { + return .{ + .years = toOption(c.OptionI64, self.years), + .months = toOption(c.OptionI64, self.months), + .weeks = toOption(c.OptionI64, self.weeks), + .days = toOption(c.OptionI64, self.days), + .hours = toOption(c.OptionI64, self.hours), + .minutes = toOption(c.OptionI64, self.minutes), + .seconds = toOption(c.OptionI64, self.seconds), + .milliseconds = toOption(c.OptionI64, self.milliseconds), + .microseconds = toOption(c.OptionF64, self.microseconds), + .nanoseconds = toOption(c.OptionF64, self.nanoseconds), + }; + } + + pub fn durRelativeTo(self: dur.RelativeTo) c.RelativeTo { + switch (self) { + .plain_date => |pd| return .{ .date = pd._inner }, + .zoned_date_time => |zdt| return .{ .zoned = zdt._inner }, + .plain_date_time => |pdt| return .{ .date = (pdt.toPlainDate() catch unreachable)._inner }, + } + } + + pub fn roundingOpts(self: t.RoundingOptions) c.RoundingOptions { + return .{ + .largest_unit = toUnitOption(to.unit(self.largest_unit)), + .smallest_unit = toUnitOption(to.unit(self.smallest_unit)), + .rounding_mode = toRoundingModeOption(to.roundingMode(self.rounding_mode)), + .increment = toOption(c.OptionU32, self.rounding_increment), + }; + } + + pub fn diffsettings(self: t.DifferenceSettings) c.DifferenceSettings { + return .{ + .largest_unit = toUnitOption(to.unit(self.largest_unit)), + .smallest_unit = toUnitOption(to.unit(self.smallest_unit)), + .rounding_mode = toRoundingModeOption(to.roundingMode(self.rounding_mode)), + .increment = toOption(c.OptionU32, self.rounding_increment), + }; + } +}; + +pub const from = struct { + pub fn sign(value: c_int) t.Sign { + return switch (value) { + c.Sign_Positive => .positive, + c.Sign_Zero => .zero, + c.Sign_Negative => .negative, + else => .zero, + }; + } +}; diff --git a/src/temporal.zig b/src/temporal.zig index c76c4a5..3738efe 100644 --- a/src/temporal.zig +++ b/src/temporal.zig @@ -1,6 +1,3 @@ -const abi = @import("abi.zig"); -const c = abi.c; - /// Time unit for Temporal operations. /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal pub const Unit = enum { @@ -15,22 +12,6 @@ pub const Unit = enum { week, month, year, - - pub fn toCApi(self: Unit) c_uint { - return switch (self) { - .auto => c.Unit_Auto, - .nanosecond => c.Unit_Nanosecond, - .microsecond => c.Unit_Microsecond, - .millisecond => c.Unit_Millisecond, - .second => c.Unit_Second, - .minute => c.Unit_Minute, - .hour => c.Unit_Hour, - .day => c.Unit_Day, - .week => c.Unit_Week, - .month => c.Unit_Month, - .year => c.Unit_Year, - }; - } }; /// Rounding mode for Temporal operations. @@ -54,20 +35,6 @@ pub const RoundingMode = enum { half_trunc, /// Round half to even (banker's rounding) half_even, - - pub fn toCApi(self: RoundingMode) c_uint { - return switch (self) { - .ceil => c.RoundingMode_Ceil, - .floor => c.RoundingMode_Floor, - .expand => c.RoundingMode_Expand, - .trunc => c.RoundingMode_Trunc, - .half_ceil => c.RoundingMode_HalfCeil, - .half_floor => c.RoundingMode_HalfFloor, - .half_expand => c.RoundingMode_HalfExpand, - .half_trunc => c.RoundingMode_HalfTrunc, - .half_even => c.RoundingMode_HalfEven, - }; - } }; /// Sign of a duration or time value. @@ -75,23 +42,6 @@ pub const Sign = enum { positive, zero, negative, - - pub fn toCApi(self: Sign) c_int { - return switch (self) { - .positive => c.Sign_Positive, - .zero => c.Sign_Zero, - .negative => c.Sign_Negative, - }; - } - - pub fn fromCApi(value: c_int) Sign { - return switch (value) { - c.Sign_Positive => .positive, - c.Sign_Zero => .zero, - c.Sign_Negative => .negative, - else => .zero, - }; - } }; /// Options for rounding operations (Instant.round, Duration.round, etc.). @@ -101,15 +51,6 @@ pub const RoundingOptions = struct { smallest_unit: ?Unit = null, rounding_mode: ?RoundingMode = null, rounding_increment: ?u32 = null, - - pub fn toCApi(self: RoundingOptions) c.RoundingOptions { - return .{ - .largest_unit = abi.toUnitOption(toCUnit(self.largest_unit)), - .smallest_unit = abi.toUnitOption(toCUnit(self.smallest_unit)), - .rounding_mode = abi.toRoundingModeOption(toCRoundingMode(self.rounding_mode)), - .increment = abi.toOption(c.OptionU32, self.rounding_increment), - }; - } }; /// Options for computing differences between instants. @@ -119,15 +60,6 @@ pub const DifferenceSettings = struct { smallest_unit: ?Unit = null, rounding_mode: ?RoundingMode = null, rounding_increment: ?u32 = null, - - pub fn toCApi(self: DifferenceSettings) c.DifferenceSettings { - return .{ - .largest_unit = abi.toUnitOption(toCUnit(self.largest_unit)), - .smallest_unit = abi.toUnitOption(toCUnit(self.smallest_unit)), - .rounding_mode = abi.toRoundingModeOption(toCRoundingMode(self.rounding_mode)), - .increment = abi.toOption(c.OptionU32, self.rounding_increment), - }; - } }; /// Options for Duration.toString() formatting. @@ -136,33 +68,16 @@ pub const ToStringRoundingOptions = struct { fractional_second_digits: ?u8 = null, smallest_unit: ?Unit = null, rounding_mode: ?RoundingMode = null, +}; - pub fn toCApi(self: ToStringRoundingOptions) c.ToStringRoundingOptions { - const precision: c.Precision = if (self.fractional_second_digits) |fsd| - .{ .is_minute = false, .precision = abi.toOption(c.OptionU8, fsd) } - else if (self.smallest_unit) |su| - switch (su) { - .second => .{ .is_minute = false, .precision = abi.toOption(c.OptionU8, 0) }, - .millisecond => .{ .is_minute = false, .precision = abi.toOption(c.OptionU8, 3) }, - .microsecond => .{ .is_minute = false, .precision = abi.toOption(c.OptionU8, 6) }, - .nanosecond => .{ .is_minute = false, .precision = abi.toOption(c.OptionU8, 9) }, - else => .{ .is_minute = false, .precision = abi.toOption(c.OptionU8, null) }, - } - else - .{ .is_minute = false, .precision = abi.toOption(c.OptionU8, null) }; +/// Time zone identifier for Temporal operations +pub const TimeZone = struct { + _inner: abi.c.TimeZone, - return .{ - .precision = precision, - .smallest_unit = abi.toUnitOption(toCUnit(self.smallest_unit)), - .rounding_mode = abi.toRoundingModeOption(toCRoundingMode(self.rounding_mode)), - }; + pub fn init(id: []const u8) TimeZone { + const view = abi.toDiplomatStringView(id); + return .{ ._inner = .{ .id = view } }; } }; -pub fn toCUnit(opt: ?Unit) ?c.Unit { - return if (opt) |u| @as(c.Unit, @intCast(u.toCApi())) else null; -} - -pub fn toCRoundingMode(opt: ?RoundingMode) ?c.RoundingMode { - return if (opt) |m| @as(c.RoundingMode, @intCast(m.toCApi())) else null; -} +const abi = @import("abi.zig");