191 lines
7.3 KiB
Zig
191 lines
7.3 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 ZonedDateTime = @import("ZonedDateTime.zig");
|
|
|
|
/// # Temporal.Now
|
|
///
|
|
/// The `Temporal.Now` namespace object contains static methods for getting the current time in various formats.
|
|
///
|
|
/// - [MDN 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: [MDN 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.
|
|
///
|
|
/// See: [MDN Temporal.Now.plainDateISO](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Now/plainDateISO)
|
|
pub fn plainDateISO(io: std.Io) !PlainDate {
|
|
const now = currentParts(io);
|
|
return PlainDate.init(now.year, now.month, now.day);
|
|
}
|
|
|
|
/// 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.
|
|
///
|
|
/// See: [MDN Temporal.Now.plainDateTimeISO](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Now/plainDateTimeISO)
|
|
pub fn plainDateTimeISO(io: std.Io) !PlainDateTime {
|
|
const now = currentParts(io);
|
|
return PlainDateTime.init(
|
|
now.year,
|
|
now.month,
|
|
now.day,
|
|
now.hour,
|
|
now.minute,
|
|
now.second,
|
|
now.millisecond,
|
|
now.microsecond,
|
|
now.nanosecond,
|
|
);
|
|
}
|
|
|
|
/// 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.
|
|
///
|
|
/// See: [MDN Temporal.Now.plainTimeISO](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Now/plainTimeISO)
|
|
pub fn plainTimeISO(io: std.Io) !PlainTime {
|
|
const now = currentParts(io);
|
|
return PlainTime.init(
|
|
now.hour,
|
|
now.minute,
|
|
now.second,
|
|
now.millisecond,
|
|
now.microsecond,
|
|
now.nanosecond,
|
|
);
|
|
}
|
|
|
|
/// Returns a time zone identifier representing the system's current time zone.
|
|
///
|
|
/// See: [MDN Temporal.Now.timeZoneId](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Now/timeZoneId)
|
|
pub fn timeZoneId() []const u8 {
|
|
return "UTC";
|
|
}
|
|
|
|
/// 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.
|
|
///
|
|
/// See: [MDN Temporal.Now.zonedDateTimeISO](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Now/zonedDateTimeISO)
|
|
pub fn zonedDateTimeISO() !ZonedDateTime {
|
|
const time_zone = try ZonedDateTime.TimeZone.init(timeZoneId());
|
|
return ZonedDateTime.fromEpochNanoseconds(currentEpochNanoseconds(), time_zone);
|
|
}
|
|
|
|
const CurrentParts = struct {
|
|
year: i32,
|
|
month: u8,
|
|
day: u8,
|
|
hour: u8,
|
|
minute: u8,
|
|
second: u8,
|
|
millisecond: u16,
|
|
microsecond: u16,
|
|
nanosecond: u16,
|
|
};
|
|
|
|
fn currentParts(io: std.Io) CurrentParts {
|
|
const ns = std.Io.Timestamp.now(io, .real).nanoseconds;
|
|
const seconds: i64 = @intCast(@divTrunc(ns, 1_000_000_000));
|
|
const subsec_nanos_u64: u64 = @intCast(@rem(ns, 1_000_000_000));
|
|
|
|
const days_since_epoch: u64 = @intCast(@divTrunc(seconds, std.time.epoch.secs_per_day));
|
|
const secs_of_day: u64 = @intCast(@mod(seconds, std.time.epoch.secs_per_day));
|
|
|
|
const epoch_day = std.time.epoch.EpochDay{ .day = @intCast(days_since_epoch) };
|
|
const year_day = epoch_day.calculateYearDay();
|
|
const month_day = year_day.calculateMonthDay();
|
|
const day_seconds = std.time.epoch.DaySeconds{ .secs = @intCast(secs_of_day) };
|
|
|
|
const millisecond: u16 = @intCast(subsec_nanos_u64 / 1_000_000);
|
|
const microsecond: u16 = @intCast((subsec_nanos_u64 / 1_000) % 1_000);
|
|
const nanosecond: u16 = @intCast(subsec_nanos_u64 % 1_000);
|
|
|
|
return .{
|
|
.year = @intCast(year_day.year),
|
|
.month = @intCast(month_day.month.numeric()),
|
|
.day = @intCast(month_day.day_index + 1),
|
|
.hour = @intCast(day_seconds.getHoursIntoDay()),
|
|
.minute = @intCast(day_seconds.getMinutesIntoHour()),
|
|
.second = @intCast(day_seconds.getSecondsIntoMinute()),
|
|
.millisecond = millisecond,
|
|
.microsecond = microsecond,
|
|
.nanosecond = nanosecond,
|
|
};
|
|
}
|
|
|
|
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;
|
|
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(io);
|
|
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;
|
|
const dt = try plainDateTimeISO(io);
|
|
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(io);
|
|
try std.testing.expect(t.hour() < 24);
|
|
try std.testing.expect(t.minute() < 60);
|
|
try std.testing.expect(t.second() < 60);
|
|
}
|
|
test timeZoneId {
|
|
const tz = timeZoneId();
|
|
try std.testing.expectEqualStrings("UTC", tz);
|
|
}
|
|
test 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);
|
|
}
|