Last active
July 26, 2024 05:17
-
-
Save zigster64/af794741555dd88c22b6aedb899c53ed to your computer and use it in GitHub Desktop.
Zig Money object with print formatting
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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