| 1 |
const std = @import("std");
|
| 2 |
const format_util = @import("format.zig");
|
| 3 |
const c = @cImport({
|
| 4 |
@cInclude("time.h");
|
| 5 |
});
|
| 6 |
|
| 7 |
pub const Date_Time = struct {
|
| 8 |
format: []const u8,
|
| 9 |
datetime_format: []const u8,
|
| 10 |
interval_secs: u64,
|
| 11 |
color: c_ulong,
|
| 12 |
|
| 13 |
pub fn init(format: []const u8, datetime_format: []const u8, interval_secs: u64, color: c_ulong) Date_Time {
|
| 14 |
return .{
|
| 15 |
.format = format,
|
| 16 |
.datetime_format = datetime_format,
|
| 17 |
.interval_secs = interval_secs,
|
| 18 |
.color = color,
|
| 19 |
};
|
| 20 |
}
|
| 21 |
|
| 22 |
pub fn content(self: *Date_Time, buffer: []u8) []const u8 {
|
| 23 |
var now: c.time_t = c.time(null);
|
| 24 |
const tm_ptr = c.localtime(&now);
|
| 25 |
if (tm_ptr == null) return buffer[0..0];
|
| 26 |
const tm = tm_ptr.*;
|
| 27 |
|
| 28 |
const hours: u32 = @intCast(tm.tm_hour);
|
| 29 |
const minutes: u32 = @intCast(tm.tm_min);
|
| 30 |
const seconds: u32 = @intCast(tm.tm_sec);
|
| 31 |
const day: u8 = @intCast(tm.tm_mday);
|
| 32 |
const month: u8 = @intCast(tm.tm_mon + 1);
|
| 33 |
const year: i32 = tm.tm_year + 1900;
|
| 34 |
const dow: i32 = tm.tm_wday;
|
| 35 |
|
| 36 |
var datetime_buf: [64]u8 = undefined;
|
| 37 |
var dt_len: usize = 0;
|
| 38 |
|
| 39 |
var fmt_idx: usize = 0;
|
| 40 |
while (fmt_idx < self.datetime_format.len and dt_len < datetime_buf.len - 10) {
|
| 41 |
if (self.datetime_format[fmt_idx] == '%' and fmt_idx + 1 < self.datetime_format.len) {
|
| 42 |
const next = self.datetime_format[fmt_idx + 1];
|
| 43 |
if (next == '-' and fmt_idx + 2 < self.datetime_format.len) {
|
| 44 |
const spec = self.datetime_format[fmt_idx + 2];
|
| 45 |
dt_len += format_spec(spec, false, hours, minutes, seconds, day, month, year, dow, datetime_buf[dt_len..]);
|
| 46 |
fmt_idx += 3;
|
| 47 |
} else {
|
| 48 |
dt_len += format_spec(next, true, hours, minutes, seconds, day, month, year, dow, datetime_buf[dt_len..]);
|
| 49 |
fmt_idx += 2;
|
| 50 |
}
|
| 51 |
} else {
|
| 52 |
datetime_buf[dt_len] = self.datetime_format[fmt_idx];
|
| 53 |
dt_len += 1;
|
| 54 |
fmt_idx += 1;
|
| 55 |
}
|
| 56 |
}
|
| 57 |
|
| 58 |
return format_util.substitute(self.format, datetime_buf[0..dt_len], buffer);
|
| 59 |
}
|
| 60 |
|
| 61 |
fn format_spec(spec: u8, pad: bool, hours: u32, minutes: u32, seconds: u32, day: u8, month: u8, year: i32, dow: i32, buf: []u8) usize {
|
| 62 |
const day_names = [_][]const u8{ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
|
| 63 |
const month_names = [_][]const u8{ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
|
| 64 |
|
| 65 |
return switch (spec) {
|
| 66 |
'Y' => (std.fmt.bufPrint(buf, "{d}", .{year}) catch return 0).len,
|
| 67 |
'm' => if (pad) (std.fmt.bufPrint(buf, "{d:0>2}", .{month}) catch return 0).len else (std.fmt.bufPrint(buf, "{d}", .{month}) catch return 0).len,
|
| 68 |
'd' => if (pad) (std.fmt.bufPrint(buf, "{d:0>2}", .{day}) catch return 0).len else (std.fmt.bufPrint(buf, "{d}", .{day}) catch return 0).len,
|
| 69 |
'H' => if (pad) (std.fmt.bufPrint(buf, "{d:0>2}", .{hours}) catch return 0).len else (std.fmt.bufPrint(buf, "{d}", .{hours}) catch return 0).len,
|
| 70 |
'M' => if (pad) (std.fmt.bufPrint(buf, "{d:0>2}", .{minutes}) catch return 0).len else (std.fmt.bufPrint(buf, "{d}", .{minutes}) catch return 0).len,
|
| 71 |
'S' => if (pad) (std.fmt.bufPrint(buf, "{d:0>2}", .{seconds}) catch return 0).len else (std.fmt.bufPrint(buf, "{d}", .{seconds}) catch return 0).len,
|
| 72 |
'I' => blk: {
|
| 73 |
const h12 = if (hours == 0) 12 else if (hours > 12) hours - 12 else hours;
|
| 74 |
break :blk if (pad) (std.fmt.bufPrint(buf, "{d:0>2}", .{h12}) catch return 0).len else (std.fmt.bufPrint(buf, "{d}", .{h12}) catch return 0).len;
|
| 75 |
},
|
| 76 |
'p' => blk: {
|
| 77 |
const s: []const u8 = if (hours >= 12) "PM" else "AM";
|
| 78 |
@memcpy(buf[0..2], s);
|
| 79 |
break :blk 2;
|
| 80 |
},
|
| 81 |
'P' => blk: {
|
| 82 |
const s: []const u8 = if (hours >= 12) "pm" else "am";
|
| 83 |
@memcpy(buf[0..2], s);
|
| 84 |
break :blk 2;
|
| 85 |
},
|
| 86 |
'a' => blk: {
|
| 87 |
const name = day_names[@intCast(dow)];
|
| 88 |
@memcpy(buf[0..3], name);
|
| 89 |
break :blk 3;
|
| 90 |
},
|
| 91 |
'b' => blk: {
|
| 92 |
const name = month_names[month - 1];
|
| 93 |
@memcpy(buf[0..3], name);
|
| 94 |
break :blk 3;
|
| 95 |
},
|
| 96 |
else => 0,
|
| 97 |
};
|
| 98 |
}
|
| 99 |
|
| 100 |
pub fn interval(self: *Date_Time) u64 {
|
| 101 |
return self.interval_secs;
|
| 102 |
}
|
| 103 |
|
| 104 |
pub fn get_color(self: *Date_Time) c_ulong {
|
| 105 |
return self.color;
|
| 106 |
}
|
| 107 |
};
|