feat: extend bindings
This commit is contained in:
parent
ba5b777de4
commit
f302c55135
6 changed files with 154 additions and 15 deletions
|
|
@ -479,7 +479,7 @@ pub fn run(allocator: std.mem.Allocator, io_optional: ?std.Io) !void {
|
|||
\\ - blank: {}
|
||||
\\ - microseconds: {d}
|
||||
\\ - toJSON(): {s}
|
||||
\\ - toLocaleString implemented: {}
|
||||
\\ - toLocaleString supported: {}
|
||||
\\
|
||||
\\
|
||||
, .{
|
||||
|
|
@ -522,16 +522,17 @@ pub fn run(allocator: std.mem.Allocator, io_optional: ?std.Io) !void {
|
|||
try instant_zdt.toString(allocator, .{}),
|
||||
});
|
||||
|
||||
const now_zdt_supported = Temporal.Now.zonedDateTimeISO() != error.TemporalNotImplemented;
|
||||
const now_zdt = try Temporal.Now.zonedDateTimeISO();
|
||||
defer now_zdt.deinit();
|
||||
std.log.info(
|
||||
\\Now Coverage
|
||||
\\ - timeZoneId(): {s}
|
||||
\\ - zonedDateTimeISO implemented: {}
|
||||
\\ - zonedDateTimeISO(): {s}
|
||||
\\
|
||||
\\
|
||||
, .{
|
||||
Temporal.Now.timeZoneId(),
|
||||
now_zdt_supported,
|
||||
try now_zdt.toString(allocator, .{}),
|
||||
});
|
||||
|
||||
const date_cal = try Temporal.PlainDate.calInit(2024, 2, 2, "iso8601");
|
||||
|
|
@ -558,7 +559,7 @@ pub fn run(allocator: std.mem.Allocator, io_optional: ?std.Io) !void {
|
|||
\\ - toPlainYearMonth: {s}
|
||||
\\ - toZonedDateTime: {s}
|
||||
\\ - toJSON(): {s}
|
||||
\\ - toLocaleString implemented: {}
|
||||
\\ - toLocaleString supported: {}
|
||||
\\ - valueOf supported: {}
|
||||
\\ - with year/month/day: {s}
|
||||
\\
|
||||
|
|
@ -736,7 +737,8 @@ pub fn run(allocator: std.mem.Allocator, io_optional: ?std.Io) !void {
|
|||
const zdt_plain_datetime = try zdt.toPlainDateTime();
|
||||
const zdt_plain_time = try zdt.toPlainTime();
|
||||
const zdt_valueof_supported = zdt.valueOf() != error.ValueOfNotSupported;
|
||||
const zdt_with_supported = zdt.with(allocator, .{ .year = 2025 }) != error.TemporalNoteImplemented;
|
||||
const zdt_with_coverage = try zdt.with(allocator, .{ .year = 2025 });
|
||||
defer zdt_with_coverage.deinit();
|
||||
std.log.info(
|
||||
\\ZonedDateTime Coverage
|
||||
\\ - init: {s}
|
||||
|
|
@ -786,7 +788,7 @@ pub fn run(allocator: std.mem.Allocator, io_optional: ?std.Io) !void {
|
|||
\\ - offset/offsetNanoseconds: {s}/{}
|
||||
\\ - weekOfYear/yearOfWeek: {?}/{?}
|
||||
\\ - valueOf supported: {}
|
||||
\\ - with implemented: {}
|
||||
\\ - with year=2025: {s}
|
||||
\\
|
||||
\\
|
||||
, .{
|
||||
|
|
@ -804,7 +806,7 @@ pub fn run(allocator: std.mem.Allocator, io_optional: ?std.Io) !void {
|
|||
zdt.weekOfYear(),
|
||||
zdt.yearOfWeek(),
|
||||
zdt_valueof_supported,
|
||||
zdt_with_supported,
|
||||
try zdt_with_coverage.toString(allocator, .{}),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -320,7 +320,8 @@ pub fn toJSON(self: Duration, allocator: std.mem.Allocator) ![]u8 {
|
|||
return self.toString(allocator, .{});
|
||||
}
|
||||
|
||||
/// Returns a string with a language-sensitive representation of this duration. Not implemented.
|
||||
/// Returns a string with a language-sensitive representation of this duration.
|
||||
/// Not implemented.
|
||||
/// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration/toLocaleString
|
||||
pub fn toLocaleString(self: Duration, allocator: std.mem.Allocator) ![]u8 {
|
||||
_ = self;
|
||||
|
|
|
|||
23
src/Now.zig
23
src/Now.zig
|
|
@ -87,7 +87,8 @@ pub fn timeZoneId() []const u8 {
|
|||
///
|
||||
/// See: [MDN Temporal.Now.zonedDateTimeISO](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Now/zonedDateTimeISO)
|
||||
pub fn zonedDateTimeISO() !ZonedDateTime {
|
||||
return error.TemporalNotImplemented;
|
||||
const time_zone = try ZonedDateTime.TimeZone.init(timeZoneId());
|
||||
return ZonedDateTime.fromEpochNanoseconds(currentEpochNanoseconds(), time_zone);
|
||||
}
|
||||
|
||||
const CurrentParts = struct {
|
||||
|
|
@ -132,6 +133,18 @@ fn currentParts(io: std.Io) CurrentParts {
|
|||
};
|
||||
}
|
||||
|
||||
fn currentEpochNanoseconds() i128 {
|
||||
var timespec: std.posix.timespec = undefined;
|
||||
switch (std.posix.errno(std.posix.system.clock_gettime(.REALTIME, ×pec))) {
|
||||
.SUCCESS => {},
|
||||
else => return 0,
|
||||
}
|
||||
|
||||
const seconds: i128 = @intCast(timespec.sec);
|
||||
const nanos: i128 = @intCast(timespec.nsec);
|
||||
return seconds * std.time.ns_per_s + nanos;
|
||||
}
|
||||
|
||||
// ---------- Tests ---------------------
|
||||
test instant {
|
||||
const io = std.testing.io;
|
||||
|
|
@ -168,5 +181,11 @@ test timeZoneId {
|
|||
try std.testing.expectEqualStrings("UTC", tz);
|
||||
}
|
||||
test zonedDateTimeISO {
|
||||
try std.testing.expectError(error.TemporalNotImplemented, zonedDateTimeISO());
|
||||
const zdt = try zonedDateTimeISO();
|
||||
defer zdt.deinit();
|
||||
|
||||
try std.testing.expect(zdt.epochNanoseconds() > 0);
|
||||
const tz = try zdt.timeZoneId(std.testing.allocator);
|
||||
defer std.testing.allocator.free(tz);
|
||||
try std.testing.expectEqualStrings("UTC", tz);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,6 +99,24 @@ pub const ToStringOptions = struct {
|
|||
time_zone_name: DisplayTimeZone = .auto,
|
||||
};
|
||||
|
||||
/// Options for `with()` method.
|
||||
pub const WithOptions = struct {
|
||||
year: ?i32 = null,
|
||||
month: ?u8 = null,
|
||||
month_code: ?[]const u8 = null,
|
||||
day: ?u8 = null,
|
||||
era: ?[]const u8 = null,
|
||||
era_year: ?i32 = null,
|
||||
hour: ?u8 = null,
|
||||
minute: ?u8 = null,
|
||||
second: ?u8 = null,
|
||||
millisecond: ?u16 = null,
|
||||
microsecond: ?u16 = null,
|
||||
nanosecond: ?u16 = null,
|
||||
offset: ?[]const u8 = null,
|
||||
time_zone: ?TimeZone = null,
|
||||
};
|
||||
|
||||
/// Helper function to wrap a C API result into a ZonedDateTime
|
||||
fn wrapZonedDateTime(result: anytype) !ZonedDateTime {
|
||||
const ptr = (try abi.extractResult(result)) orelse return abi.TemporalError.Generic;
|
||||
|
|
@ -273,9 +291,21 @@ pub fn valueOf(_: ZonedDateTime) !void {
|
|||
/// See [MDN Temporal.ZonedDateTime.prototype.with()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime/with)
|
||||
pub fn with(self: ZonedDateTime, allocator: std.mem.Allocator, fields: anytype) !ZonedDateTime {
|
||||
_ = allocator;
|
||||
_ = fields;
|
||||
_ = self;
|
||||
return error.TemporalNoteImplemented; // Need PartialZonedDateTime mapping
|
||||
const partial = abi.toPartialZonedDateTime(fields);
|
||||
const disambiguation = abi.toOption(abi.c.Disambiguation_option, abi.to.toDisambiguation(Disambiguation.compatible));
|
||||
const offset_option = abi.toOption(abi.c.OffsetDisambiguation_option, abi.to.toOffsetDisambiguation(OffsetDisambiguation.prefer_offset));
|
||||
const overflow = abi.c.ArithmeticOverflow_option{
|
||||
.is_ok = true,
|
||||
.unnamed_0 = .{ .ok = abi.c.ArithmeticOverflow_Constrain },
|
||||
};
|
||||
|
||||
return wrapZonedDateTime(abi.c.temporal_rs_ZonedDateTime_with(
|
||||
self._inner,
|
||||
partial,
|
||||
disambiguation,
|
||||
offset_option,
|
||||
overflow,
|
||||
));
|
||||
}
|
||||
|
||||
/// Returns a new ZonedDateTime interpreted in the new calendar system.
|
||||
|
|
@ -760,7 +790,14 @@ test valueOf {
|
|||
test with {
|
||||
const zdt = try from("2021-01-01T12:00:00+00:00[UTC]", null, .compatible, .reject);
|
||||
defer zdt.deinit();
|
||||
try std.testing.expectError(error.TemporalNoteImplemented, zdt.with(std.testing.allocator, .{}));
|
||||
|
||||
const result = try zdt.with(std.testing.allocator, .{ .year = 2022, .month = 2, .day = 3, .hour = 4 });
|
||||
defer result.deinit();
|
||||
|
||||
try std.testing.expectEqual(@as(i32, 2022), result.year());
|
||||
try std.testing.expectEqual(@as(u8, 2), result.month());
|
||||
try std.testing.expectEqual(@as(u8, 3), result.day());
|
||||
try std.testing.expectEqual(@as(u8, 4), result.hour());
|
||||
}
|
||||
|
||||
test withCalendar {
|
||||
|
|
|
|||
79
src/abi.zig
79
src/abi.zig
|
|
@ -90,6 +90,85 @@ pub fn toTimeZoneOption(maybe_value: ?c.TimeZone) c.TimeZone_option {
|
|||
return toOption(c.TimeZone_option, maybe_value);
|
||||
}
|
||||
|
||||
pub fn toPartialZonedDateTime(fields: anytype) c.PartialZonedDateTime {
|
||||
return .{
|
||||
.date = .{
|
||||
.year = toI32OptionField(fields, "year"),
|
||||
.month = toU8OptionField(fields, "month"),
|
||||
.month_code = toStringViewField(fields, "month_code"),
|
||||
.day = toU8OptionField(fields, "day"),
|
||||
.era = toStringViewField(fields, "era"),
|
||||
.era_year = toI32OptionField(fields, "era_year"),
|
||||
.calendar = c.AnyCalendarKind_Iso,
|
||||
},
|
||||
.time = .{
|
||||
.hour = toU8OptionField(fields, "hour"),
|
||||
.minute = toU8OptionField(fields, "minute"),
|
||||
.second = toU8OptionField(fields, "second"),
|
||||
.millisecond = toU16OptionField(fields, "millisecond"),
|
||||
.microsecond = toU16OptionField(fields, "microsecond"),
|
||||
.nanosecond = toU16OptionField(fields, "nanosecond"),
|
||||
},
|
||||
.offset = toOptionStringViewField(fields, "offset"),
|
||||
.timezone = toTimeZoneOptionField(fields, "time_zone"),
|
||||
};
|
||||
}
|
||||
|
||||
fn toI32OptionField(fields: anytype, comptime name: []const u8) c.OptionI32 {
|
||||
return toOption(c.OptionI32, intField(i32, fields, name));
|
||||
}
|
||||
|
||||
fn toU8OptionField(fields: anytype, comptime name: []const u8) c.OptionU8 {
|
||||
return toOption(c.OptionU8, intField(u8, fields, name));
|
||||
}
|
||||
|
||||
fn toU16OptionField(fields: anytype, comptime name: []const u8) c.OptionU16 {
|
||||
return toOption(c.OptionU16, intField(u16, fields, name));
|
||||
}
|
||||
|
||||
fn intField(comptime Int: type, fields: anytype, comptime name: []const u8) ?Int {
|
||||
if (!@hasField(@TypeOf(fields), name)) return null;
|
||||
|
||||
const value = @field(fields, name);
|
||||
return switch (@typeInfo(@TypeOf(value))) {
|
||||
.optional => if (value) |payload| @as(Int, @intCast(payload)) else null,
|
||||
else => @as(Int, @intCast(value)),
|
||||
};
|
||||
}
|
||||
|
||||
fn toStringViewField(fields: anytype, comptime name: []const u8) c.DiplomatStringView {
|
||||
if (stringField(fields, name)) |value| return toDiplomatStringView(value);
|
||||
return .{ .data = null, .len = 0 };
|
||||
}
|
||||
|
||||
fn toOptionStringViewField(fields: anytype, comptime name: []const u8) c.OptionStringView {
|
||||
if (stringField(fields, name)) |value| {
|
||||
return .{ .is_ok = true, .unnamed_0 = .{ .ok = toDiplomatStringView(value) } };
|
||||
}
|
||||
return .{ .is_ok = false };
|
||||
}
|
||||
|
||||
fn stringField(fields: anytype, comptime name: []const u8) ?[]const u8 {
|
||||
if (!@hasField(@TypeOf(fields), name)) return null;
|
||||
|
||||
const value = @field(fields, name);
|
||||
return switch (@typeInfo(@TypeOf(value))) {
|
||||
.optional => value,
|
||||
else => value,
|
||||
};
|
||||
}
|
||||
|
||||
fn toTimeZoneOptionField(fields: anytype, comptime name: []const u8) c.TimeZone_option {
|
||||
if (!@hasField(@TypeOf(fields), name)) return .{ .is_ok = false };
|
||||
|
||||
const value = @field(fields, name);
|
||||
const maybe_time_zone = switch (@typeInfo(@TypeOf(value))) {
|
||||
.optional => if (value) |payload| payload._inner else null,
|
||||
else => value._inner,
|
||||
};
|
||||
return toOption(c.TimeZone_option, maybe_time_zone);
|
||||
}
|
||||
|
||||
/// Convert a Zig `?Unit` to a Rust `Option<Unit>`.
|
||||
pub fn toUnitOption(maybe_value: ?c.Unit) c.Unit_option {
|
||||
return toOption(c.Unit_option, maybe_value);
|
||||
|
|
|
|||
|
|
@ -502,6 +502,7 @@ test ZonedDateTime {
|
|||
"DisplayOffset",
|
||||
"DisplayTimeZone",
|
||||
"ToStringOptions",
|
||||
"WithOptions",
|
||||
};
|
||||
|
||||
try assertDecls(ZonedDateTime, checks);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue