authorgravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2021-06-26 15:21:27+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-06-27 12:54:31+03:00
logf398ac3ee48b35754f51f0bfaff76b6a1e70da77
tree4136cd37830bba4f946c8a121ba4e5ed2eba74ab
parentef56e42a2a69e85d185257c5bd0b3f12532f2f5d

std/fmt: add fmtDurationSigned

When working with durations it often makes sense to use signed integers and allow negative durations, and there is currently no nice way to format these in std.fmt. This patch adds a simple wrapper for the existing fmtDurtion to fit this need.

1 files changed, 81 insertions(+), 0 deletions(-)

lib/std/fmt.zig+81
......@@ -1461,6 +1461,87 @@ test "fmtDuration" {
14611461 }
14621462}
14631463
1464fn formatDurationSigned(ns: i64, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
1465 if (ns < 0) {
1466 try writer.writeByte('-');
1467 try formatDuration(@intCast(u64, -ns), fmt, options, writer);
1468 } else {
1469 try formatDuration(@intCast(u64, ns), fmt, options, writer);
1470 }
1471}
1472
1473/// Return a Formatter for number of nanoseconds according to its signed magnitude:
1474/// [#y][#w][#d][#h][#m]#[.###][n|u|m]s
1475pub fn fmtDurationSigned(ns: i64) Formatter(formatDurationSigned) {
1476 return .{ .data = ns };
1477}
1478
1479test "fmtDurationSigned" {
1480 var buf: [24]u8 = undefined;
1481 inline for (.{
1482 .{ .s = "0ns", .d = 0 },
1483 .{ .s = "1ns", .d = 1 },
1484 .{ .s = "-1ns", .d = -(1) },
1485 .{ .s = "999ns", .d = std.time.ns_per_us - 1 },
1486 .{ .s = "-999ns", .d = -(std.time.ns_per_us - 1) },
1487 .{ .s = "1us", .d = std.time.ns_per_us },
1488 .{ .s = "-1us", .d = -(std.time.ns_per_us) },
1489 .{ .s = "1.45us", .d = 1450 },
1490 .{ .s = "-1.45us", .d = -(1450) },
1491 .{ .s = "1.5us", .d = 3 * std.time.ns_per_us / 2 },
1492 .{ .s = "-1.5us", .d = -(3 * std.time.ns_per_us / 2) },
1493 .{ .s = "14.5us", .d = 14500 },
1494 .{ .s = "-14.5us", .d = -(14500) },
1495 .{ .s = "145us", .d = 145000 },
1496 .{ .s = "-145us", .d = -(145000) },
1497 .{ .s = "999.999us", .d = std.time.ns_per_ms - 1 },
1498 .{ .s = "-999.999us", .d = -(std.time.ns_per_ms - 1) },
1499 .{ .s = "1ms", .d = std.time.ns_per_ms + 1 },
1500 .{ .s = "-1ms", .d = -(std.time.ns_per_ms + 1) },
1501 .{ .s = "1.5ms", .d = 3 * std.time.ns_per_ms / 2 },
1502 .{ .s = "-1.5ms", .d = -(3 * std.time.ns_per_ms / 2) },
1503 .{ .s = "1.11ms", .d = 1110000 },
1504 .{ .s = "-1.11ms", .d = -(1110000) },
1505 .{ .s = "1.111ms", .d = 1111000 },
1506 .{ .s = "-1.111ms", .d = -(1111000) },
1507 .{ .s = "1.111ms", .d = 1111100 },
1508 .{ .s = "-1.111ms", .d = -(1111100) },
1509 .{ .s = "999.999ms", .d = std.time.ns_per_s - 1 },
1510 .{ .s = "-999.999ms", .d = -(std.time.ns_per_s - 1) },
1511 .{ .s = "1s", .d = std.time.ns_per_s },
1512 .{ .s = "-1s", .d = -(std.time.ns_per_s) },
1513 .{ .s = "59.999s", .d = std.time.ns_per_min - 1 },
1514 .{ .s = "-59.999s", .d = -(std.time.ns_per_min - 1) },
1515 .{ .s = "1m", .d = std.time.ns_per_min },
1516 .{ .s = "-1m", .d = -(std.time.ns_per_min) },
1517 .{ .s = "1h", .d = std.time.ns_per_hour },
1518 .{ .s = "-1h", .d = -(std.time.ns_per_hour) },
1519 .{ .s = "1d", .d = std.time.ns_per_day },
1520 .{ .s = "-1d", .d = -(std.time.ns_per_day) },
1521 .{ .s = "1w", .d = std.time.ns_per_week },
1522 .{ .s = "-1w", .d = -(std.time.ns_per_week) },
1523 .{ .s = "1y", .d = 365 * std.time.ns_per_day },
1524 .{ .s = "-1y", .d = -(365 * std.time.ns_per_day) },
1525 .{ .s = "1y52w23h59m59.999s", .d = 730 * std.time.ns_per_day - 1 }, // 365d = 52w1d
1526 .{ .s = "-1y52w23h59m59.999s", .d = -(730 * std.time.ns_per_day - 1) }, // 365d = 52w1d
1527 .{ .s = "1y1h1.001s", .d = 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + std.time.ns_per_ms },
1528 .{ .s = "-1y1h1.001s", .d = -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + std.time.ns_per_ms) },
1529 .{ .s = "1y1h1s", .d = 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + 999 * std.time.ns_per_us },
1530 .{ .s = "-1y1h1s", .d = -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_s + 999 * std.time.ns_per_us) },
1531 .{ .s = "1y1h999.999us", .d = 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms - 1 },
1532 .{ .s = "-1y1h999.999us", .d = -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms - 1) },
1533 .{ .s = "1y1h1ms", .d = 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms },
1534 .{ .s = "-1y1h1ms", .d = -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms) },
1535 .{ .s = "1y1h1ms", .d = 365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms + 1 },
1536 .{ .s = "-1y1h1ms", .d = -(365 * std.time.ns_per_day + std.time.ns_per_hour + std.time.ns_per_ms + 1) },
1537 .{ .s = "1y1m999ns", .d = 365 * std.time.ns_per_day + std.time.ns_per_min + 999 },
1538 .{ .s = "-1y1m999ns", .d = -(365 * std.time.ns_per_day + std.time.ns_per_min + 999) },
1539 }) |tc| {
1540 const slice = try bufPrint(&buf, "{}", .{fmtDurationSigned(tc.d)});
1541 try std.testing.expectEqualStrings(tc.s, slice);
1542 }
1543}
1544
14641545pub const ParseIntError = error{
14651546 /// The result cannot fit in the type specified
14661547 Overflow,