535 lines
21 KiB
Zig
535 lines
21 KiB
Zig
const std = @import("std");
|
|
const abi = @import("abi.zig");
|
|
const t = @import("temporal.zig");
|
|
|
|
const PlainDate = @import("PlainDate.zig");
|
|
const Duration = @import("Duration.zig");
|
|
|
|
/// # Temporal.PlainYearMonth
|
|
///
|
|
/// The `Temporal.PlainYearMonth` object represents a particular month in a specific year, with no day or time.
|
|
///
|
|
/// - [MDN Temporal.PlainYearMonth](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth)
|
|
const PlainYearMonth = @This();
|
|
|
|
_inner: *abi.c.PlainYearMonth,
|
|
|
|
// Import types from temporal.zig
|
|
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 {
|
|
auto,
|
|
always,
|
|
never,
|
|
critical,
|
|
};
|
|
|
|
pub const ToStringOptions = struct {
|
|
calendar_display: ?CalendarDisplay = null,
|
|
};
|
|
|
|
pub const WithOptions = struct {
|
|
year: ?i32 = null,
|
|
month: ?u8 = null,
|
|
month_code: ?[]const u8 = null,
|
|
};
|
|
|
|
// Helper to wrap PlainYearMonth pointer
|
|
fn wrapPlainYearMonth(result: anytype) !PlainYearMonth {
|
|
const ptr = (try abi.extractResult(result)) orelse return abi.TemporalError.Generic;
|
|
|
|
return .{ ._inner = ptr };
|
|
}
|
|
|
|
/// Creates a new PlainYearMonth from the given year, month, and optional calendar.
|
|
/// Equivalent to the Temporal.PlainYearMonth constructor.
|
|
/// See [MDN Temporal.PlainYearMonth() constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/PlainYearMonth)
|
|
pub fn init(year_val: i32, month_val: u8, calendar: ?[]const u8) !PlainYearMonth {
|
|
const cal_kind = if (calendar) |cal| blk: {
|
|
const cal_view = abi.toDiplomatStringView(cal);
|
|
const cal_result = abi.c.temporal_rs_AnyCalendarKind_parse_temporal_calendar_string(cal_view);
|
|
break :blk try abi.extractResult(cal_result);
|
|
} else abi.c.AnyCalendarKind_Iso;
|
|
|
|
const overflow = abi.c.ArithmeticOverflow_Constrain;
|
|
const ref_day = abi.c.OptionU8{ .is_ok = false };
|
|
|
|
return wrapPlainYearMonth(abi.c.temporal_rs_PlainYearMonth_try_new_with_overflow(
|
|
year_val,
|
|
month_val,
|
|
ref_day,
|
|
cal_kind,
|
|
overflow,
|
|
));
|
|
}
|
|
|
|
/// Parses a PlainYearMonth from a string.
|
|
/// See [MDN Temporal.PlainYearMonth.from()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/from)
|
|
pub fn from(s: []const u8) !PlainYearMonth {
|
|
return fromUtf8(s);
|
|
}
|
|
|
|
fn fromUtf8(utf8: []const u8) !PlainYearMonth {
|
|
const view = abi.toDiplomatStringView(utf8);
|
|
return wrapPlainYearMonth(abi.c.temporal_rs_PlainYearMonth_from_utf8(view));
|
|
}
|
|
|
|
fn fromUtf16(utf16: []const u16) !PlainYearMonth {
|
|
const view = abi.toDiplomatString16View(utf16);
|
|
return wrapPlainYearMonth(abi.c.temporal_rs_PlainYearMonth_from_utf16(view));
|
|
}
|
|
|
|
// Comparison
|
|
/// Compares two PlainYearMonth instances by their ISO date values.
|
|
/// Returns -1, 0, or 1 if the first is before, equal, or after the second.
|
|
/// See [MDN Temporal.PlainYearMonth.compare()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/compare)
|
|
pub fn compare(a: PlainYearMonth, b: PlainYearMonth) i8 {
|
|
return abi.c.temporal_rs_PlainYearMonth_compare(a._inner, b._inner);
|
|
}
|
|
|
|
/// Returns true if this PlainYearMonth is equal to another (same ISO date and calendar).
|
|
/// See [MDN Temporal.PlainYearMonth.prototype.equals()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/equals)
|
|
pub fn equals(self: PlainYearMonth, other: PlainYearMonth) bool {
|
|
return abi.c.temporal_rs_PlainYearMonth_equals(self._inner, other._inner);
|
|
}
|
|
|
|
// Arithmetic
|
|
/// Returns a new PlainYearMonth moved forward by the given duration.
|
|
/// See [MDN Temporal.PlainYearMonth.prototype.add()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/add)
|
|
pub fn add(self: PlainYearMonth, duration: Duration) !PlainYearMonth {
|
|
const overflow = abi.c.ArithmeticOverflow_Constrain;
|
|
return wrapPlainYearMonth(abi.c.temporal_rs_PlainYearMonth_add(self._inner, duration._inner, overflow));
|
|
}
|
|
|
|
/// Returns a new PlainYearMonth moved backward by the given duration.
|
|
/// See [MDN Temporal.PlainYearMonth.prototype.subtract()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/subtract)
|
|
pub fn subtract(self: PlainYearMonth, duration: Duration) !PlainYearMonth {
|
|
const overflow = abi.c.ArithmeticOverflow_Constrain;
|
|
return wrapPlainYearMonth(abi.c.temporal_rs_PlainYearMonth_subtract(self._inner, duration._inner, overflow));
|
|
}
|
|
|
|
/// Returns the duration from this PlainYearMonth to another.
|
|
/// See [MDN Temporal.PlainYearMonth.prototype.until()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/until)
|
|
pub fn until(self: PlainYearMonth, other: PlainYearMonth, options: DifferenceSettings) !Duration {
|
|
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 };
|
|
}
|
|
|
|
/// Returns the duration from another PlainYearMonth to this one.
|
|
/// See [MDN Temporal.PlainYearMonth.prototype.since()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/since)
|
|
pub fn since(self: PlainYearMonth, other: PlainYearMonth, options: DifferenceSettings) !Duration {
|
|
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 };
|
|
}
|
|
|
|
// Property accessors
|
|
/// Returns the calendar identifier used to interpret the internal ISO 8601 date.
|
|
/// See [MDN Temporal.PlainYearMonth.prototype.calendarId](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/calendarId)
|
|
pub fn calendarId(self: PlainYearMonth, allocator: std.mem.Allocator) ![]u8 {
|
|
const calendar_ptr = abi.c.temporal_rs_PlainYearMonth_calendar(self._inner) orelse return error.TemporalError;
|
|
const cal_id_view = abi.c.temporal_rs_Calendar_identifier(calendar_ptr);
|
|
return try allocator.dupe(u8, cal_id_view.data[0..cal_id_view.len]);
|
|
}
|
|
|
|
/// Returns the year of this year-month relative to the calendar's epoch.
|
|
/// See [MDN Temporal.PlainYearMonth.prototype.year](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/year)
|
|
pub fn year(self: PlainYearMonth) i32 {
|
|
return abi.c.temporal_rs_PlainYearMonth_year(self._inner);
|
|
}
|
|
|
|
/// Returns the 1-based month index in the year of this year-month.
|
|
/// See [MDN Temporal.PlainYearMonth.prototype.month](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/month)
|
|
pub fn month(self: PlainYearMonth) u8 {
|
|
return abi.c.temporal_rs_PlainYearMonth_month(self._inner);
|
|
}
|
|
|
|
/// Returns the calendar-specific string representing the month of this year-month.
|
|
/// See [MDN Temporal.PlainYearMonth.prototype.monthCode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/monthCode)
|
|
pub fn monthCode(self: PlainYearMonth, allocator: std.mem.Allocator) ![]const u8 {
|
|
var write = abi.DiplomatWrite.init(allocator);
|
|
defer write.deinit();
|
|
|
|
abi.c.temporal_rs_PlainYearMonth_month_code(self._inner, &write.inner);
|
|
return try write.toOwnedSlice();
|
|
}
|
|
|
|
/// Returns the number of days in the month of this year-month.
|
|
/// See [MDN Temporal.PlainYearMonth.prototype.daysInMonth](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/daysInMonth)
|
|
pub fn daysInMonth(self: PlainYearMonth) u16 {
|
|
return abi.c.temporal_rs_PlainYearMonth_days_in_month(self._inner);
|
|
}
|
|
|
|
/// Returns the number of days in the year of this year-month.
|
|
/// See [MDN Temporal.PlainYearMonth.prototype.daysInYear](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/daysInYear)
|
|
pub fn daysInYear(self: PlainYearMonth) u16 {
|
|
return abi.c.temporal_rs_PlainYearMonth_days_in_year(self._inner);
|
|
}
|
|
|
|
/// Returns the number of months in the year of this year-month.
|
|
/// See [MDN Temporal.PlainYearMonth.prototype.monthsInYear](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/monthsInYear)
|
|
pub fn monthsInYear(self: PlainYearMonth) u16 {
|
|
return abi.c.temporal_rs_PlainYearMonth_months_in_year(self._inner);
|
|
}
|
|
|
|
/// Returns true if this year-month is in a leap year.
|
|
/// See [MDN Temporal.PlainYearMonth.prototype.inLeapYear](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/inLeapYear)
|
|
pub fn inLeapYear(self: PlainYearMonth) bool {
|
|
return abi.c.temporal_rs_PlainYearMonth_in_leap_year(self._inner);
|
|
}
|
|
|
|
/// Returns the calendar-specific era of this year-month, or null if not applicable.
|
|
/// See [MDN Temporal.PlainYearMonth.prototype.era](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/era)
|
|
pub fn era(self: PlainYearMonth, allocator: std.mem.Allocator) !?[]const u8 {
|
|
var write = abi.DiplomatWrite.init(allocator);
|
|
defer write.deinit();
|
|
|
|
abi.c.temporal_rs_PlainYearMonth_era(self._inner, &write.inner);
|
|
const result = try write.toOwnedSlice();
|
|
if (result.len == 0) return null;
|
|
return result;
|
|
}
|
|
|
|
/// Returns the year of this year-month within the era, or null if not applicable.
|
|
/// See [MDN Temporal.PlainYearMonth.prototype.eraYear](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/eraYear)
|
|
pub fn eraYear(self: PlainYearMonth) ?i32 {
|
|
const result = abi.c.temporal_rs_PlainYearMonth_era_year(self._inner);
|
|
if (!result.is_ok) return null;
|
|
return result.unnamed_0.ok;
|
|
}
|
|
|
|
// Modification
|
|
/// Returns a new PlainYearMonth with some fields replaced by new values.
|
|
/// See [MDN Temporal.PlainYearMonth.prototype.with()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/with)
|
|
pub fn with(self: PlainYearMonth, options: WithOptions) !PlainYearMonth {
|
|
// Build month_code view
|
|
const month_code_view = if (options.month_code) |mc|
|
|
abi.toDiplomatStringView(mc)
|
|
else
|
|
abi.c.DiplomatStringView{ .data = null, .len = 0 };
|
|
|
|
// Build partial date with only the fields we want to modify
|
|
const partial_date = abi.c.PartialDate{
|
|
.year = if (options.year) |y| abi.toOption(abi.c.OptionI32, y) else .{ .is_ok = false },
|
|
.month = if (options.month) |m| abi.toOption(abi.c.OptionU8, m) else .{ .is_ok = false },
|
|
.day = .{ .is_ok = false },
|
|
.month_code = month_code_view,
|
|
.era = .{ .data = null, .len = 0 },
|
|
.era_year = .{ .is_ok = false },
|
|
.calendar = abi.c.AnyCalendarKind_Iso,
|
|
};
|
|
|
|
const overflow = abi.c.ArithmeticOverflow_option{
|
|
.is_ok = true,
|
|
.unnamed_0 = .{ .ok = abi.c.ArithmeticOverflow_Constrain },
|
|
};
|
|
|
|
return wrapPlainYearMonth(abi.c.temporal_rs_PlainYearMonth_with(
|
|
self._inner,
|
|
partial_date,
|
|
overflow,
|
|
));
|
|
}
|
|
|
|
// Conversion
|
|
/// Returns a PlainDate representing this year-month and a supplied day in the same calendar system.
|
|
/// See [MDN Temporal.PlainYearMonth.prototype.toPlainDate()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/toPlainDate)
|
|
pub fn toPlainDate(self: PlainYearMonth, day: u8) !PlainDate {
|
|
const partial_date = abi.c.PartialDate_option{
|
|
.is_ok = true,
|
|
.unnamed_0 = .{
|
|
.ok = .{
|
|
.year = .{ .is_ok = false },
|
|
.month = .{ .is_ok = false },
|
|
.day = abi.toOption(abi.c.OptionU8, day),
|
|
.month_code = .{ .data = null, .len = 0 },
|
|
.era = .{ .data = null, .len = 0 },
|
|
.era_year = .{ .is_ok = false },
|
|
.calendar = abi.c.AnyCalendarKind_Iso,
|
|
},
|
|
},
|
|
};
|
|
|
|
const result = abi.c.temporal_rs_PlainYearMonth_to_plain_date(self._inner, partial_date);
|
|
const ptr = (try abi.extractResult(result)) orelse return abi.TemporalError.Generic;
|
|
|
|
return PlainDate{ ._inner = ptr };
|
|
}
|
|
|
|
// String conversions
|
|
/// Returns a string representing this year-month in RFC 9557 format.
|
|
/// See [MDN Temporal.PlainYearMonth.prototype.toString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/toString)
|
|
pub fn toString(self: PlainYearMonth, allocator: std.mem.Allocator) ![]u8 {
|
|
return toStringWithOptions(self, allocator, .{});
|
|
}
|
|
|
|
fn toStringWithOptions(self: PlainYearMonth, allocator: std.mem.Allocator, options: ToStringOptions) ![]u8 {
|
|
_ = options;
|
|
var write = abi.DiplomatWrite.init(allocator);
|
|
defer write.deinit();
|
|
|
|
const display = abi.c.DisplayCalendar_Auto;
|
|
abi.c.temporal_rs_PlainYearMonth_to_ixdtf_string(self._inner, display, &write.inner);
|
|
|
|
return try write.toOwnedSlice();
|
|
}
|
|
|
|
/// Returns a JSON string representing this year-month.
|
|
/// See [MDN Temporal.PlainYearMonth.prototype.toJSON()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/toJSON)
|
|
pub fn toJSON(self: PlainYearMonth, allocator: std.mem.Allocator) ![]u8 {
|
|
return toString(self, allocator);
|
|
}
|
|
|
|
/// Returns a locale-sensitive string representing this year-month.
|
|
/// See [MDN Temporal.PlainYearMonth.prototype.toLocaleString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainYearMonth/toLocaleString)
|
|
pub fn toLocaleString(self: PlainYearMonth, allocator: std.mem.Allocator) ![]u8 {
|
|
return toString(self, allocator);
|
|
}
|
|
|
|
/// Throws a TypeError, as PlainYearMonth objects cannot be converted to primitive values.
|
|
/// See [MDN Temporal.PlainYearMonth.prototype.valueOf()](https://developer.mozilla
|
|
pub fn valueOf(self: PlainYearMonth) !void {
|
|
_ = self;
|
|
return error.ValueError;
|
|
}
|
|
|
|
// ---------- Tests ---------------------
|
|
|
|
test init {
|
|
const ym = try init(2024, 12, null);
|
|
try std.testing.expectEqual(@as(i32, 2024), ym.year());
|
|
try std.testing.expectEqual(@as(u8, 12), ym.month());
|
|
}
|
|
|
|
test from {
|
|
const ym = try from("2024-12");
|
|
try std.testing.expectEqual(@as(i32, 2024), ym.year());
|
|
try std.testing.expectEqual(@as(u8, 12), ym.month());
|
|
}
|
|
|
|
test compare {
|
|
{
|
|
const ym1 = try init(2024, 12, null);
|
|
const ym2 = try init(2024, 12, null);
|
|
try std.testing.expectEqual(@as(i8, 0), compare(ym1, ym2));
|
|
}
|
|
{
|
|
const ym1 = try init(2024, 11, null);
|
|
const ym2 = try init(2024, 12, null);
|
|
try std.testing.expectEqual(@as(i8, -1), compare(ym1, ym2));
|
|
}
|
|
|
|
{
|
|
const ym1 = try init(2025, 1, null);
|
|
const ym2 = try init(2024, 12, null);
|
|
try std.testing.expectEqual(@as(i8, 1), compare(ym1, ym2));
|
|
}
|
|
|
|
{
|
|
const ym1 = try init(2024, 12, null);
|
|
const ym2 = try init(2024, 12, null);
|
|
try std.testing.expect(ym1.equals(ym2));
|
|
}
|
|
}
|
|
|
|
test equals {
|
|
{
|
|
const ym1 = try init(2024, 12, null);
|
|
const ym2 = try init(2024, 12, null);
|
|
try std.testing.expect(ym1.equals(ym2));
|
|
}
|
|
|
|
{
|
|
const ym1 = try init(2024, 12, null);
|
|
const ym2 = try init(2024, 11, null);
|
|
try std.testing.expect(!ym1.equals(ym2));
|
|
}
|
|
}
|
|
|
|
test add {
|
|
const ym = try init(2024, 6, null);
|
|
const duration = try Duration.from("P6M");
|
|
const result = try ym.add(duration);
|
|
try std.testing.expectEqual(@as(i32, 2024), result.year());
|
|
try std.testing.expectEqual(@as(u8, 12), result.month());
|
|
}
|
|
|
|
test subtract {
|
|
const ym = try init(2024, 12, null);
|
|
const duration = try Duration.from("P6M");
|
|
const result = try ym.subtract(duration);
|
|
try std.testing.expectEqual(@as(i32, 2024), result.year());
|
|
try std.testing.expectEqual(@as(u8, 6), result.month());
|
|
}
|
|
|
|
test daysInMonth {
|
|
const ym = try init(2024, 2, null);
|
|
try std.testing.expectEqual(@as(u16, 29), ym.daysInMonth()); // 2024 is a leap year
|
|
}
|
|
|
|
test daysInYear {
|
|
const ym = try init(2024, 1, null);
|
|
try std.testing.expectEqual(@as(u16, 366), ym.daysInYear()); // 2024 is a leap year
|
|
}
|
|
|
|
test monthsInYear {
|
|
const ym = try init(2024, 1, null);
|
|
try std.testing.expectEqual(@as(u16, 12), ym.monthsInYear());
|
|
}
|
|
|
|
test inLeapYear {
|
|
const ym2024 = try init(2024, 1, null);
|
|
const ym2023 = try init(2023, 1, null);
|
|
try std.testing.expect(ym2024.inLeapYear());
|
|
try std.testing.expect(!ym2023.inLeapYear());
|
|
}
|
|
|
|
test toPlainDate {
|
|
const ym = try init(2024, 12, null);
|
|
const date = try ym.toPlainDate(25);
|
|
try std.testing.expectEqual(@as(i32, 2024), date.year());
|
|
try std.testing.expectEqual(@as(u8, 12), date.month());
|
|
try std.testing.expectEqual(@as(u8, 25), date.day());
|
|
}
|
|
|
|
test toString {
|
|
const ym = try init(2024, 12, null);
|
|
const str = try ym.toString(std.testing.allocator);
|
|
defer std.testing.allocator.free(str);
|
|
try std.testing.expect(str.len > 0);
|
|
try std.testing.expect(std.mem.indexOf(u8, str, "2024") != null);
|
|
}
|
|
|
|
test toJSON {
|
|
const ym = try init(2024, 12, null);
|
|
const str = try ym.toJSON(std.testing.allocator);
|
|
defer std.testing.allocator.free(str);
|
|
try std.testing.expect(str.len > 0);
|
|
}
|
|
|
|
test since {
|
|
const ym1 = try init(2024, 12, null);
|
|
const ym2 = try init(2024, 6, null);
|
|
const dur = try ym1.since(ym2, .{});
|
|
|
|
try std.testing.expectEqual(@as(i64, 6), dur.months());
|
|
}
|
|
|
|
test until {
|
|
const ym1 = try init(2024, 6, null);
|
|
const ym2 = try init(2024, 12, null);
|
|
const dur = try ym1.until(ym2, .{});
|
|
|
|
try std.testing.expectEqual(@as(i64, 6), dur.months());
|
|
}
|
|
|
|
test calendarId {
|
|
const ym = try from("2021-07-01[u-ca=gregory]");
|
|
const cal_id = try ym.calendarId(std.testing.allocator);
|
|
defer std.testing.allocator.free(cal_id);
|
|
try std.testing.expectEqualStrings("gregory", cal_id);
|
|
}
|
|
|
|
test year {
|
|
const ym = try from("2021-07");
|
|
try std.testing.expectEqual(@as(i32, 2021), ym.year());
|
|
}
|
|
|
|
test month {
|
|
const ym = try from("2021-07");
|
|
try std.testing.expectEqual(@as(u8, 7), ym.month());
|
|
}
|
|
|
|
test monthCode {
|
|
const ym = try from("2021-07");
|
|
const month_code = try ym.monthCode(std.testing.allocator);
|
|
defer std.testing.allocator.free(month_code);
|
|
try std.testing.expectEqualStrings("M07", month_code);
|
|
}
|
|
|
|
test era {
|
|
const ym = try from("2021-07-01[u-ca=gregory]");
|
|
const maybe_era = try ym.era(std.testing.allocator);
|
|
const era_value = maybe_era orelse return error.TestUnexpectedResult;
|
|
defer std.testing.allocator.free(era_value);
|
|
try std.testing.expectEqualStrings("ce", era_value);
|
|
}
|
|
|
|
test eraYear {
|
|
const ym = try from("2021-07-01[u-ca=gregory]");
|
|
try std.testing.expectEqual(@as(?i32, 2021), ym.eraYear());
|
|
}
|
|
|
|
test with {
|
|
// Test modifying year
|
|
const ym1 = try init(2024, 6, null);
|
|
const ym2 = try ym1.with(.{ .year = 2025 });
|
|
try std.testing.expectEqual(@as(i32, 2025), ym2.year());
|
|
try std.testing.expectEqual(@as(u8, 6), ym2.month());
|
|
|
|
// Test modifying month
|
|
const ym3 = try init(2024, 6, null);
|
|
const ym4 = try ym3.with(.{ .month = 12 });
|
|
try std.testing.expectEqual(@as(i32, 2024), ym4.year());
|
|
try std.testing.expectEqual(@as(u8, 12), ym4.month());
|
|
|
|
// Test modifying both
|
|
const ym5 = try init(2024, 6, null);
|
|
const ym6 = try ym5.with(.{ .year = 2025, .month = 1 });
|
|
try std.testing.expectEqual(@as(i32, 2025), ym6.year());
|
|
try std.testing.expectEqual(@as(u8, 1), ym6.month());
|
|
}
|
|
|
|
test toLocaleString {
|
|
const ym = try init(2024, 6, null);
|
|
const str = try ym.toLocaleString(std.testing.allocator);
|
|
defer std.testing.allocator.free(str);
|
|
try std.testing.expect(str.len > 0);
|
|
try std.testing.expect(std.mem.indexOf(u8, str, "2024") != null);
|
|
}
|
|
|
|
test "props" {
|
|
const ym = try from("2021-07-01[u-ca=gregory]");
|
|
|
|
const cal_id = try ym.calendarId(std.testing.allocator);
|
|
defer std.testing.allocator.free(cal_id);
|
|
try std.testing.expectEqualStrings("gregory", cal_id);
|
|
|
|
try std.testing.expectEqual(@as(i32, 2021), ym.year());
|
|
try std.testing.expectEqual(@as(u8, 7), ym.month());
|
|
|
|
const month_code = try ym.monthCode(std.testing.allocator);
|
|
defer std.testing.allocator.free(month_code);
|
|
try std.testing.expectEqualStrings("M07", month_code);
|
|
try std.testing.expectEqual(@as(u16, 31), ym.daysInMonth());
|
|
try std.testing.expectEqual(@as(u16, 365), ym.daysInYear());
|
|
try std.testing.expectEqual(@as(u16, 12), ym.monthsInYear());
|
|
try std.testing.expect(ym.inLeapYear() == false);
|
|
|
|
const eraa = try ym.era(std.testing.allocator);
|
|
if (eraa) |e| {
|
|
defer std.testing.allocator.free(e);
|
|
try std.testing.expectEqualStrings("ce", e);
|
|
} else {
|
|
try std.testing.expect(false);
|
|
}
|
|
|
|
const era_year = ym.eraYear();
|
|
if (era_year) |ey| {
|
|
try std.testing.expectEqual(@as(i32, 2021), ey);
|
|
} else {
|
|
try std.testing.expect(false);
|
|
}
|
|
}
|
|
|
|
test valueOf {
|
|
const ym = try init(2024, 12, null);
|
|
try std.testing.expectError(error.ValueError, ym.valueOf());
|
|
}
|