| ... | ... | @@ -1,6 +1,7 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | const string = []const u8; |
| 3 | 3 | const range = @import("range").range; |
| 4 | const time = @This(); |
| 4 | 5 | |
| 5 | 6 | pub const DateTime = struct { |
| 6 | 7 | ms: u16, |
| ... | ... | @@ -161,16 +162,11 @@ pub const DateTime = struct { |
| 161 | 162 | } |
| 162 | 163 | |
| 163 | 164 | pub fn isLeapYear(self: Self) bool { |
| 164 | | const y = self.years; |
| 165 | | var ret = false; |
| 166 | | if (y % 4 == 0) ret = true; |
| 167 | | if (y % 100 == 0) ret = false; |
| 168 | | if (y % 400 == 0) ret = true; |
| 169 | | return ret; |
| 165 | return time.isLeapYear(self.years); |
| 170 | 166 | } |
| 171 | 167 | |
| 172 | 168 | pub fn daysThisYear(self: Self) u64 { |
| 173 | | return if (self.isLeapYear()) 366 else 365; |
| 169 | return time.daysInYear(self.years); |
| 174 | 170 | } |
| 175 | 171 | |
| 176 | 172 | pub fn daysThisMonth(self: Self) u16 { |
| ... | ... | @@ -178,10 +174,7 @@ pub const DateTime = struct { |
| 178 | 174 | } |
| 179 | 175 | |
| 180 | 176 | fn daysInMonth(self: Self, month: u16) u16 { |
| 181 | | const norm = [12]u16{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; |
| 182 | | const leap = [12]u16{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; |
| 183 | | const month_days = if (!self.isLeapYear()) norm else leap; |
| 184 | | return month_days[month]; |
| 177 | return time.daysInMonth(self.years, month); |
| 185 | 178 | } |
| 186 | 179 | |
| 187 | 180 | fn incrementWeekday(self: *Self, count: u64) void { |
| ... | ... | @@ -199,6 +192,29 @@ pub const DateTime = struct { |
| 199 | 192 | return ret; |
| 200 | 193 | } |
| 201 | 194 | |
| 195 | // pub fn toUnix(self: Self) u64 { |
| 196 | // const x = self.toUnix(); |
| 197 | // return x / 1000; |
| 198 | // } |
| 199 | |
| 200 | pub fn toUnixMilli(self: Self) u64 { |
| 201 | var res: u64 = 0; |
| 202 | res += self.ms; |
| 203 | res += @as(u64, self.seconds) * std.time.ms_per_s; |
| 204 | res += @as(u64, self.minutes) * std.time.ms_per_min; |
| 205 | res += @as(u64, self.hours) * std.time.ms_per_hour; |
| 206 | res += self.daysSinceEpoch() * std.time.ms_per_day; |
| 207 | return res; |
| 208 | } |
| 209 | |
| 210 | fn daysSinceEpoch(self: Self) u64 { |
| 211 | var res: u64 = 0; |
| 212 | res += self.days; |
| 213 | for (range(self.years - epoch_unix.years)) |_, i| res += time.daysInYear(@intCast(u16, i)); |
| 214 | for (range(self.months)) |_, i| res += self.daysInMonth(@intCast(u16, i)); |
| 215 | return res; |
| 216 | } |
| 217 | |
| 202 | 218 | /// fmt is based on https://momentjs.com/docs/#/displaying/format/ |
| 203 | 219 | pub fn format(self: Self, comptime fmt: string, options: std.fmt.FormatOptions, writer: anytype) !void { |
| 204 | 220 | _ = options; |
| ... | ... | @@ -239,6 +255,7 @@ pub const DateTime = struct { |
| 239 | 255 | .DDD => try writer.print("{}", .{self.dayOfThisYear() + 1}), |
| 240 | 256 | .DDDo => try printOrdinal(writer, self.dayOfThisYear() + 1), |
| 241 | 257 | .DDDD => try writer.print("{:0>3}", .{self.dayOfThisYear() + 1}), |
| 258 | |
| 242 | 259 | .d => try writer.print("{}", .{@enumToInt(self.weekday)}), |
| 243 | 260 | .do => try printOrdinal(writer, @enumToInt(self.weekday)), |
| 244 | 261 | .dd => try writer.writeAll(@tagName(self.weekday)[0..2]), |
| ... | ... | @@ -283,7 +300,8 @@ pub const DateTime = struct { |
| 283 | 300 | .Z => try writer.writeAll("+00:00"), |
| 284 | 301 | .ZZ => try writer.writeAll("+0000"), |
| 285 | 302 | |
| 286 | | else => @compileError("'" ++ @tagName(tag) ++ "' not currently supported"), |
| 303 | .x => try writer.print("{}", .{self.toUnixMilli()}), |
| 304 | // .X => try writer.print("{}", .{self.toUnix()}), |
| 287 | 305 | } |
| 288 | 306 | next = null; |
| 289 | 307 | s = i; |
| ... | ... | @@ -365,8 +383,8 @@ pub const DateTime = struct { |
| 365 | 383 | z, // EST CST ... MST PST |
| 366 | 384 | Z, // -07:00 -06:00 ... +06:00 +07:00 |
| 367 | 385 | ZZ, // -0700 -0600 ... +0600 +0700 |
| 368 | | X, // unix |
| 369 | 386 | x, // unix milli |
| 387 | // X, // unix |
| 370 | 388 | }; |
| 371 | 389 | }; |
| 372 | 390 | |
| ... | ... | @@ -414,6 +432,25 @@ pub const Era = enum { |
| 414 | 432 | AD, |
| 415 | 433 | }; |
| 416 | 434 | |
| 435 | pub fn isLeapYear(year: u16) bool { |
| 436 | var ret = false; |
| 437 | if (year % 4 == 0) ret = true; |
| 438 | if (year % 100 == 0) ret = false; |
| 439 | if (year % 400 == 0) ret = true; |
| 440 | return ret; |
| 441 | } |
| 442 | |
| 443 | pub fn daysInYear(year: u16) u16 { |
| 444 | return if (isLeapYear(year)) 366 else 365; |
| 445 | } |
| 446 | |
| 447 | fn daysInMonth(year: u16, month: u16) u16 { |
| 448 | const norm = [12]u16{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; |
| 449 | const leap = [12]u16{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; |
| 450 | const month_days = if (!isLeapYear(year)) norm else leap; |
| 451 | return month_days[month]; |
| 452 | } |
| 453 | |
| 417 | 454 | fn printOrdinal(writer: anytype, num: u16) !void { |
| 418 | 455 | try writer.print("{}", .{num}); |
| 419 | 456 | try writer.writeAll(switch (num) { |