oxwm

https://git.tonybtw.com/oxwm.git git://git.tonybtw.com/oxwm.git
4,718 bytes raw
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
};