/
ms.c
146 lines (121 loc) · 3.31 KB
/
ms.c
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
145
//
// ms.c
//
// Copyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca>
//
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "asprintf/asprintf.h"
#include "ms.h"
// microseconds
#define US_MSEC (long long) 1000
#define US_SEC 1000 * US_MSEC
#define US_MIN 60 * US_SEC
#define US_HOUR 60 * US_MIN
#define US_DAY 24 * US_HOUR
#define US_WEEK 7 * US_DAY
#define US_YEAR 52 * US_WEEK
// milliseconds
#define MS_SEC (long long)1000
#define MS_MIN 60 * MS_SEC
#define MS_HOUR 60 * MS_MIN
#define MS_DAY 24 * MS_HOUR
#define MS_WEEK 7 * MS_DAY
#define MS_YEAR 52 * MS_WEEK
/*
* Convert the given `str` representation to microseconds,
* for example "10ms", "5s", "2m", "1h" etc.
*/
long long
string_to_microseconds(const char *str) {
size_t len = strlen(str);
long long val = strtoll(str, NULL, 10);
if (!val) return -1;
switch (str[len - 1]) {
case 's': return 'm' == str[len - 2] ? val * 1000 : val * US_SEC;
case 'm': return val * US_MIN;
case 'h': return val * US_HOUR;
case 'd': return val * US_DAY;
case 'w': return val * US_WEEK;
case 'y': return val * US_YEAR;
default: return val;
}
}
/*
* Convert the given `str` representation to milliseconds,
* for example "10ms", "5s", "2m", "1h" etc.
*/
long long
string_to_milliseconds(const char *str) {
size_t len = strlen(str);
long long val = strtoll(str, NULL, 10);
if (!val) return -1;
switch (str[len - 1]) {
case 's': return 'm' == str[len - 2] ? val : val * 1000;
case 'm': return val * MS_MIN;
case 'h': return val * MS_HOUR;
case 'd': return val * MS_DAY;
case 'w': return val * MS_WEEK;
case 'y': return val * MS_YEAR;
default: return val;
}
}
/*
* Convert the given `str` representation to seconds.
*/
long long
string_to_seconds(const char *str) {
long long ret = string_to_milliseconds(str);
if (-1 == ret) return ret;
return ret / 1000;
}
/*
* Convert the given `ms` to a string. This
* value must be `free()`d by the developer.
*/
char *
milliseconds_to_string(long long ms) {
char *str = NULL;
long long div = 1;
char *fmt;
if (ms < MS_SEC) fmt = "%lldms";
else if (ms < MS_MIN) { fmt = "%llds"; div = MS_SEC; }
else if (ms < MS_HOUR) { fmt = "%lldm"; div = MS_MIN; }
else if (ms < MS_DAY) { fmt = "%lldh"; div = MS_HOUR; }
else if (ms < MS_WEEK) { fmt = "%lldd"; div = MS_DAY; }
else if (ms < MS_YEAR) { fmt = "%lldw"; div = MS_WEEK; }
else { fmt = "%lldy"; div = MS_YEAR; }
if (-1 == asprintf(&str, fmt, ms / div)) {
return NULL;
}
return str;
}
/*
* Convert the given `ms` to a long string. This
* value must be `free()`d by the developer.
*/
char *
milliseconds_to_long_string(long long ms) {
long long div;
char *name;
char *str = NULL;
if (ms < MS_SEC) {
if (-1 == asprintf(&str, "less than one second")) return NULL;
return str;
}
if (ms < MS_MIN) { name = "second"; div = MS_SEC; }
else if (ms < MS_HOUR) { name = "minute"; div = MS_MIN; }
else if (ms < MS_DAY) { name = "hour"; div = MS_HOUR; }
else if (ms < MS_WEEK) { name = "day"; div = MS_DAY; }
else if (ms < MS_YEAR) { name = "week"; div = MS_WEEK; }
else { name = "year"; div = MS_YEAR; }
long long val = ms / div;
char *fmt = 1 == val
? "%lld %s"
: "%lld %ss";
if (-1 == asprintf(&str, fmt, val, name)) {
return NULL;
}
return str;
}