temporalz/src/Now.zig
2026-07-16 01:36:14 +06:00

183 lines
7.8 KiB
Zig

const std = @import("std");
const Instant = @import("Instant.zig");
const PlainDate = @import("PlainDate.zig");
const PlainDateTime = @import("PlainDateTime.zig");
const PlainTime = @import("PlainTime.zig");
const SystemTimeZone = @import("SystemTimeZone.zig");
const ZonedDateTime = @import("ZonedDateTime.zig");
const abi = @import("abi.zig");
/// # Temporal.Now
///
/// The `Temporal.Now` namespace object contains static methods for getting the current time in various formats.
///
/// See: [Temporal.Now](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Now)
///
/// ## Description
///
/// Unlike most global objects, `Temporal.Now` is not a constructor. All properties and methods are static.
///
/// ## Example
///
/// ```js
/// Temporal.Now.instant();
/// Temporal.Now.plainDateISO();
/// Temporal.Now.plainDateTimeISO();
/// Temporal.Now.plainTimeISO();
/// Temporal.Now.timeZoneId();
/// Temporal.Now.zonedDateTimeISO();
/// ```
const Now = @This();
/// Returns the current time as a [`Temporal.Instant`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Instant) object.
///
/// See: [Temporal.Now.instant](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Now/instant)
pub fn instant(io: std.Io) !Instant {
const ns = std.Io.Timestamp.now(io, .real).nanoseconds;
return Instant.fromEpochNanoseconds(ns);
}
/// Returns the current date as a [`Temporal.PlainDate`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainDate) object, in the ISO 8601 calendar and the specified time zone.
///
/// When `time_zone_like` is null, the system time zone is used.
///
/// See: [Temporal.Now.plainDateISO](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Now/plainDateISO)
pub fn plainDateISO(allocator: std.mem.Allocator, io: std.Io, time_zone_like: ?[]const u8) !PlainDate {
const time_zone = try resolveTimeZone(allocator, io, time_zone_like);
const now = try instant(io);
defer now.deinit();
const ptr = (try abi.extractResult(abi.c.temporal_rs_PlainDate_from_epoch_nanoseconds(
abi.toI128Nanoseconds(now.epochNanoseconds()),
abi.to.toTimeZone(time_zone),
))) orelse return abi.TemporalError.Generic;
return .{ ._inner = ptr };
}
/// Returns the current date and time as a [`Temporal.PlainDateTime`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainDateTime) object, in the ISO 8601 calendar and the specified time zone.
///
/// When `time_zone_like` is null, the system time zone is used.
///
/// See: [Temporal.Now.plainDateTimeISO](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Now/plainDateTimeISO)
pub fn plainDateTimeISO(allocator: std.mem.Allocator, io: std.Io, time_zone_like: ?[]const u8) !PlainDateTime {
const time_zone = try resolveTimeZone(allocator, io, time_zone_like);
const now = try instant(io);
defer now.deinit();
const ptr = (try abi.extractResult(abi.c.temporal_rs_PlainDateTime_from_epoch_nanoseconds(
abi.toI128Nanoseconds(now.epochNanoseconds()),
abi.to.toTimeZone(time_zone),
))) orelse return abi.TemporalError.Generic;
return .{ ._inner = ptr };
}
/// Returns the current time as a [`Temporal.PlainTime`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainTime) object, in the specified time zone.
///
/// When `time_zone_like` is null, the system time zone is used.
///
/// See: [Temporal.Now.plainTimeISO](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Now/plainTimeISO)
pub fn plainTimeISO(allocator: std.mem.Allocator, io: std.Io, time_zone_like: ?[]const u8) !PlainTime {
const zdt = try zonedDateTimeISO(allocator, io, time_zone_like);
defer zdt.deinit();
return zdt.toPlainTime();
}
/// Returns a time zone identifier representing the system's current time zone.
///
/// The caller owns the returned slice and must free it with `allocator`.
///
/// See: [Temporal.Now.timeZoneId](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Now/timeZoneId)
pub fn timeZoneId(allocator: std.mem.Allocator, io: std.Io) ![]const u8 {
const time_zone = try SystemTimeZone.timeZone(allocator, io);
var write = abi.DiplomatWrite.init(allocator);
defer write.deinit();
abi.c.temporal_rs_TimeZone_identifier(time_zone._inner, &write.inner);
return try write.toOwnedSlice();
}
/// Returns the current date and time as a [`Temporal.ZonedDateTime`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/ZonedDateTime) object, in the ISO 8601 calendar and the specified time zone.
///
/// When `time_zone_like` is null, the system time zone is used.
///
/// See: [Temporal.Now.zonedDateTimeISO](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Now/zonedDateTimeISO)
pub fn zonedDateTimeISO(allocator: std.mem.Allocator, io: std.Io, time_zone_like: ?[]const u8) !ZonedDateTime {
const now = try instant(io);
defer now.deinit();
const time_zone = try resolveTimeZone(allocator, io, time_zone_like);
return ZonedDateTime.fromEpochNanoseconds(now.epochNanoseconds(), time_zone);
}
fn resolveTimeZone(allocator: std.mem.Allocator, io: std.Io, time_zone_like: ?[]const u8) !ZonedDateTime.TimeZone {
if (time_zone_like) |id| return ZonedDateTime.TimeZone.init(id);
return SystemTimeZone.timeZone(allocator, io);
}
test instant {
const io = std.testing.io;
const inst = try instant(io);
defer inst.deinit();
try std.testing.expect(inst.epochNanoseconds() > 0);
}
test plainDateISO {
const io = std.testing.io;
const date = try plainDateISO(std.testing.allocator, io, null);
defer date.deinit();
try std.testing.expect(date.year() >= 1970);
try std.testing.expect(date.month() >= 1 and date.month() <= 12);
try std.testing.expect(date.day() >= 1 and date.day() <= 31);
}
test plainDateTimeISO {
const io = std.testing.io;
var dt = try plainDateTimeISO(std.testing.allocator, io, null);
defer dt.deinit();
try std.testing.expect(dt.year() >= 1970);
try std.testing.expect(dt.month() >= 1 and dt.month() <= 12);
try std.testing.expect(dt.day() >= 1 and dt.day() <= 31);
try std.testing.expect(dt.hour() < 24);
try std.testing.expect(dt.minute() < 60);
}
test plainTimeISO {
const io = std.testing.io;
const t = try plainTimeISO(std.testing.allocator, io, null);
try std.testing.expect(t.hour() < 24);
try std.testing.expect(t.minute() < 60);
try std.testing.expect(t.second() < 60);
}
test timeZoneId {
const io = std.testing.io;
const tz = try timeZoneId(std.testing.allocator, io);
defer std.testing.allocator.free(tz);
try std.testing.expect(tz.len > 0);
_ = try ZonedDateTime.TimeZone.init(tz);
}
test zonedDateTimeISO {
const io = std.testing.io;
const zdt = try zonedDateTimeISO(std.testing.allocator, io, null);
defer zdt.deinit();
try std.testing.expect(zdt.epochNanoseconds() > 0);
const tz = try zdt.timeZoneId(std.testing.allocator);
defer std.testing.allocator.free(tz);
const expected_tz = try timeZoneId(std.testing.allocator, io);
defer std.testing.allocator.free(expected_tz);
try std.testing.expectEqualStrings(expected_tz, tz);
}
test "plainDateISO with explicit time zone" {
const io = std.testing.io;
const date = try plainDateISO(std.testing.allocator, io, "UTC");
defer date.deinit();
const zdt = try zonedDateTimeISO(std.testing.allocator, io, "UTC");
defer zdt.deinit();
const plain = try zdt.toPlainDate();
defer plain.deinit();
try std.testing.expect(date.equals(plain));
}