diff --git a/licenses.txt b/licenses.txt index d4c94a95e939601ac7a79c42e59b40136b7f73e1..830ca100462ce8e12dbcbaceb924f0edbd5eed3d 100644 --- a/licenses.txt +++ b/licenses.txt @@ -1,4 +1,5 @@ MIT: = https://spdx.org/licenses/MIT - This +- git https://github.com/nektro/zig-expect - git https://github.com/nektro/zig-extras diff --git a/test.zig b/test.zig index b1febcf680a765f3c3a0287175d010d23449b91d..142afbb945031175af88e6de6fec641408fd4dee 100644 --- a/test.zig +++ b/test.zig @@ -1,6 +1,7 @@ const std = @import("std"); const string = []const u8; const time = @import("time"); +const expect = @import("expect").expect; pub fn main() !void { std.log.info("All your codebase are belong to us.", .{}); @@ -158,3 +159,59 @@ test { t = t.addYears(1); try expectFmt(t, "YYYY-MM-DD hh:mm:ss A z", "2013-03-01 08:09:22 AM UTC"); } + +// src/test/moment/add_subtract.js +test { + // var a = moment(), + // b, + // c, + // d; + // a.year(2011); + // a.month(9); + // a.date(12); + // a.hours(6); + // a.minutes(7); + // a.seconds(8); + // a.milliseconds(500); + + // assert.equal(a.add({ ms: 50 }).milliseconds(), 550, 'Add milliseconds'); + try expect(time.DateTime.init(2011, 9, 11, 6, 7, 8, 500).addMs(50).ms).toEqual(550); + // assert.equal(a.add({ s: 1 }).seconds(), 9, 'Add seconds'); + try expect(time.DateTime.init(2011, 9, 11, 6, 7, 8, 500).addSecs(1).seconds).toEqual(9); + // assert.equal(a.add({ m: 1 }).minutes(), 8, 'Add minutes'); + try expect(time.DateTime.init(2011, 9, 11, 6, 7, 8, 500).addMins(1).minutes).toEqual(8); + // assert.equal(a.add({ h: 1 }).hours(), 7, 'Add hours'); + try expect(time.DateTime.init(2011, 9, 11, 6, 7, 8, 500).addHours(1).hours).toEqual(7); + // assert.equal(a.add({ d: 1 }).date(), 13, 'Add date'); + try expect(time.DateTime.init(2011, 9, 11, 6, 7, 8, 500).addDays(1).days).toEqual(12); + // assert.equal(a.add({ w: 1 }).date(), 20, 'Add week'); + try expect(time.DateTime.init(2011, 9, 11, 6, 7, 8, 500).addWeeks(1).days).toEqual(18); //TODO: + // assert.equal(a.add({ M: 1 }).month(), 10, 'Add month'); + try expect(time.DateTime.init(2011, 9, 11, 6, 7, 8, 500).addMonths(1).months).toEqual(10); + // assert.equal(a.add({ y: 1 }).year(), 2012, 'Add year'); + try expect(time.DateTime.init(2011, 9, 11, 6, 7, 8, 500).addYears(1).years).toEqual(2012); + // assert.equal(a.add({ Q: 1 }).month(), 1, 'Add quarter'); + try expect(time.DateTime.init(2011, 9, 11, 6, 7, 8, 500).addQuarters(1).months).toEqual(0); //TODO: + + // b = moment([2010, 0, 31]).add({ M: 1 }); + // c = moment([2010, 1, 28]).subtract({ M: 1 }); + // d = moment([2010, 1, 28]).subtract({ Q: 1 }); + + // assert.equal(b.month(), 1, 'add month, jan 31st to feb 28th'); + try expect(time.DateTime.init(2010, 0, 30, 0, 0, 0, 0).addMonths(1).toISOString()).toEqualString("2010-02-28T00:00:00Z"); + try expect(time.DateTime.init(2010, 0, 30, 0, 0, 0, 0).addMonths(1).months).toEqual(1); + try expect(time.DateTime.init(2009, 11, 30, 0, 0, 0, 0).addMonths(2).toISOString()).toEqualString("2010-02-28T00:00:00Z"); + try expect(time.DateTime.init(2009, 11, 30, 0, 0, 0, 0).addMonths(2).months).toEqual(1); + // assert.equal(b.date(), 28, 'add month, jan 31st to feb 28th'); + try expect(time.DateTime.init(2010, 0, 30, 0, 0, 0, 0).addMonths(1).days).toEqual(27); + // assert.equal(c.month(), 0, 'subtract month, feb 28th to jan 28th'); + // try expect(time.DateTime.init(2010, 1, 27, 0, 0, 0, 0).subMonths(1).months).toEqual(0); + // assert.equal(c.date(), 28, 'subtract month, feb 28th to jan 28th'); + // try expect(time.DateTime.init(2010, 1, 27, 0, 0, 0, 0).subMonths(1).days).toEqual(28); + // assert.equal(d.month(), 10, 'subtract quarter, feb 28th 2010 to nov 28th 2009'); + // try expect(time.DateTime.init(2010, 1, 27, 0, 0, 0, 0).subQuarters(1).months).toEqual(10); + // assert.equal(d.date(), 28, 'subtract quarter, feb 28th 2010 to nov 28th 2009'); + // try expect(time.DateTime.init(2010, 1, 27, 0, 0, 0, 0).subQuarters(1).days).toEqual(28); + // assert.equal(d.year(), 2009, 'subtract quarter, feb 28th 2010 to nov 28th 2009'); + // try expect(time.DateTime.init(2010, 1, 27, 0, 0, 0, 0).subQuarters(1).years).toEqual(2009); +} diff --git a/time.zig b/time.zig index 372fe6b9d253af6438a856cf36bdf5244a6f4fd9..aea0aea004bc2da7abec213c95d4f2d62597a2a0 100644 --- a/time.zig +++ b/time.zig @@ -24,14 +24,15 @@ pub const DateTime = struct { } /// Caller asserts that this is > epoch - pub fn init(year: u16, month: u16, day: u16, hr: u16, min: u16, sec: u16) Self { + pub fn init(year: u16, month: u16, day: u16, hr: u16, min: u16, sec: u16, ms: u16) Self { return epoch_unix .addYears(year - epoch_unix.years) .addMonths(month) .addDays(day) .addHours(hr) .addMins(min) - .addSecs(sec); + .addSecs(sec) + .addMs(ms); } pub fn now() Self { @@ -49,6 +50,16 @@ pub const DateTime = struct { .timezone = .UTC, }; + pub fn toISOString(self: Self) [20]u8 { + // "2021-10-21T23:20:30Z" + var result: [20]u8 = @splat(0); + var fbs = std.io.fixedBufferStream(&result); + self.format("YYYY-MM-DD HH:mm:ss", .{}, fbs.writer()) catch unreachable; + result[10] = 'T'; + result[19] = 'Z'; + return result; + } + pub fn eql(self: Self, other: Self) bool { return self.ms == other.ms and self.seconds == other.seconds and @@ -120,7 +131,7 @@ pub const DateTime = struct { { const month_len = result.daysThisMonth(); if (result.days + input > month_len) { - const left = month_len - result.days; + const left = month_len -| result.days; input -= left; result.months += 1; result.days = 0; @@ -146,15 +157,21 @@ pub const DateTime = struct { return result; } + pub fn addWeeks(self: Self, count: u64) Self { + if (count == 0) return self; + return self.addDays(7).addWeeks(count - 1); + } + pub fn addMonths(self: Self, count: u64) Self { if (count == 0) return self; var result = self; var input = count; - while (input > 0) { - const new = result.addDays(result.daysThisMonth()); - result = new; - input -= 1; - } + result.years += @intCast(input / 12); + input %= 12; + result.months += @intCast(input); + if (result.months >= 12) result.years += 1; + result.months %= 12; + result.days = @min(result.days, result.daysInMonth(result.months) - 1); return result; } @@ -166,6 +183,11 @@ pub const DateTime = struct { return result; } + pub fn addQuarters(self: Self, count: u64) Self { + if (count == 0) return self; + return self.addMonths(3).addQuarters(count - 1); + } + pub fn isLeapYear(self: Self) bool { return time.isLeapYear(self.years); } @@ -199,10 +221,10 @@ pub const DateTime = struct { pub fn toUnixMilli(self: Self) u64 { var res: u64 = 0; res += self.ms; - res += @as(u64, self.seconds) * std.time.ms_per_s; - res += @as(u64, self.minutes) * std.time.ms_per_min; - res += @as(u64, self.hours) * std.time.ms_per_hour; - res += self.daysSinceEpoch() * std.time.ms_per_day; + res += @as(u64, self.seconds) * ms_per_s; + res += @as(u64, self.minutes) * ms_per_min; + res += @as(u64, self.hours) * ms_per_hour; + res += self.daysSinceEpoch() * ms_per_day; return res; } diff --git a/zig.mod b/zig.mod index 6e5c78e1269f1cfdc492cb657bac8772d43e27c1..e10d4c41310e98664514ef3cceffcfd6cc0b784c 100644 --- a/zig.mod +++ b/zig.mod @@ -6,3 +6,5 @@ description: A date and time parsing and formatting library for Zig. min_zig_version: 0.11.0-dev.1681+0bb178bbb dependencies: - src: git https://github.com/nektro/zig-extras +root_dependencies: + - src: git https://github.com/nektro/zig-expect