Skip to content

Instantly share code, notes, and snippets.

@zigster64
Last active July 26, 2024 05:17
Show Gist options
  • Save zigster64/af794741555dd88c22b6aedb899c53ed to your computer and use it in GitHub Desktop.
Save zigster64/af794741555dd88c22b6aedb899c53ed to your computer and use it in GitHub Desktop.
Zig Money object with print formatting
// Instantiate one of these structs, and use it in print statements to get formatted output
//
// Set the .value if you know the float value, or .string if you have a string value
// Set the currency to override the currency prefix
//
// Will format the number using commas, so 1234.56 -> 1,234.56 for example
//
// If Negative, will wrap the output in a <span class="negative"></span> (which turns it red)
// and places the negative sign outside the currency symbol
// Hack/Change this suit
const std = @import("std");
value: ?f64 = null,
string: ?[]const u8 = null,
currency: []const u8 = "$",
pub fn format(self: @This(), comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
var value = self.value orelse 0.0;
if (self.value == null) {
if (self.string) |string| {
value = std.fmt.parseFloat(f64, string) catch 0.0;
} else return;
}
const is_negative = (value < 0.0);
if (is_negative) {
try writer.writeAll("<span class=\"negative\">-");
}
try writer.writeAll(self.currency);
var buffer: [64]u8 = undefined;
var string_value = try std.fmt.bufPrint(&buffer, "{d:.2}", .{value});
if (is_negative) string_value = string_value[1..];
const decimal_index = std.mem.indexOfScalar(u8, string_value, '.') orelse string_value.len;
var index: usize = 0;
for (string_value[0..decimal_index], 0..) |c, i| {
if (i > 0 and (decimal_index - i) % 3 == 0) {
try writer.writeAll(",");
index += 1;
}
try writer.writeByte(c);
index += 1;
}
try writer.writeAll(string_value[decimal_index..]);
if (is_negative) {
try writer.writeAll("</span>");
}
}
test "format money" {
const Self = @This();
var buffer: [64]u8 = undefined;
const dollars = try std.fmt.bufPrint(&buffer, "{}", .{Self{ .string = "1234.5" }});
try std.testing.expectEqualStrings("$1,234.50", dollars);
const dollars2 = try std.fmt.bufPrint(&buffer, "{}", .{Self{ .value = 1234.5 }});
try std.testing.expectEqualStrings("$1,234.50", dollars2);
const pounds = try std.fmt.bufPrint(&buffer, "{}", .{Self{ .currency = "GBP ", .value = 1234.56 }});
try std.testing.expectEqualStrings("GBP 1,234.56", pounds);
const neg = try std.fmt.bufPrint(&buffer, "{}", .{Self{ .currency = "$ ", .value = -123.45 }});
try std.testing.expectEqualStrings("<span class=\"negative\">-$ 123.45</span>", neg);
const rubles = try std.fmt.bufPrint(&buffer, "{}", .{Self{ .currency = "Rub ", .string = "234.56" }});
try std.testing.expectEqualStrings("Rub 234.56", rubles);
const rubles2 = try std.fmt.bufPrint(&buffer, "{}", .{Self{ .currency = "Rub ", .string = "122334.56" }});
try std.testing.expectEqualStrings("Rub 122,334.56", rubles2);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment