summaryrefslogtreecommitdiff
path: root/lib/timetostr.c
blob: 0d4e9a5e14c916c8f8cb2e35e6855c3f0e7eb7b4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#include <lib.h>
#include <time.h>

static char* ABB_WEEKDAY[7] = {
    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};

static char* FULL_WEEKDAY[7] = {
    "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturady"
};

static char* ABB_MONTH[12] = {
    "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};

static char* FULL_MONTH[12] = {
    "January", "Feburary", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
};

static char *write_num(unsigned int num, unsigned int pad, char *buf, size_t n) {
    size_t digits = 1;
    unsigned int x = num;

    while (x /= 10, x > 0) digits++;
    if (pad == 0) pad = digits;

    for (size_t i = 0; i < pad; i++) {

        size_t digit;
        if (i >= digits) {
            digit = 0;
        } else {
            digit = num % 10;
            num /= 10;
        }

        if (pad - i - 1 >= n) continue;
        buf[pad - i - 1] = '0' + digit;

    }

    if (pad > n) pad = n;

    return buf + pad;
}

void timetostr(time_t *time, char *format, char *buf, size_t n) {
    char *index = buf;
    char c;
    int space;

    while (
        c = *format++,
        space = (buf + n) - index,
        c != '\0' && space > 0
    ) {
        if (c != '%') {
            *index++ = c;
            continue;
        } else {
            c = *format++;
        }

        switch (c) {
            case '%':
                *index++ = '%';
                break;
            case 'a':
                index = strncpy(index, ABB_WEEKDAY[time->wday], space);
                break;
            case 'A':
                index = strncpy(index, FULL_WEEKDAY[time->wday], space);
                break;
            case 'b':
            case 'h':
                index = strncpy(index, ABB_MONTH[time->mon], space);
                break;
            case 'B':
                index = strncpy(index, FULL_MONTH[time->mon], space);
                break;
            case 'C':
                index = write_num(time->cen, 0, index, space);
                break;
            case 'd':
                index = write_num(time->mday, 2, index, space);
                break;
            case 'H':
                index = write_num(time->hour, 2, index, space);
                break;
            case 'I':
                index = write_num((time->hour + 12) % 12 + 1, 2, index, space);
                break;
            case 'j':
                index = write_num(time->yday, 3, index, space);
                break;
            case 'm':
                index = write_num(time->mon + 1, 2, index, space);
                break;
            case 'M':
                index = write_num(time->min, 2, index, space);
                break;
            case 'n':
                *index++ = '\n';
                break;
            case 'p':
                index = strncpy(index, time->hour > 11 ? "PM" : "AM", space);
                break;
            case 'P':
                index = strncpy(index, time->hour > 11 ? "pm" : "am", space);
                break;
            case 'q':
                index = write_num((time->mon + 3) / 3, 0, index, space);
                break;
            case 'S':
                index = write_num(time->sec, 2, index, space);
                break;
            case 't':
                *index++ = '\t';
                break;
            case 'u':
                index = write_num(((time->wday + 1 )% 7) + 1, 0, index, space);
                break;
            case 'w':
                index = write_num(time->wday, 0, index, space);
                break;
            case 'y':
                index = write_num(time->yn, 2, index, space);
                break;
            case 'Y':
                index = write_num(time->year + 1900, 0, index, space);
                break;
            default: {
                char b[3] = {'%', c, '\0'};
                index = strncpy(index, b, space);
                break;
            }
        }
    }

    if (space < 1)
        buf[n - 1] = '\0';
    else
        *index = '\0';
}