├── .gitignore ├── .travis.yml ├── Makefile ├── package.json ├── ms.h ├── History.md ├── Readme.md ├── test.c └── ms.c /.gitignore: -------------------------------------------------------------------------------- 1 | deps 2 | test 3 | *.o 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | before_install: 3 | - sudo apt-get update 4 | - sudo apt-get install libcurl4-gnutls-dev valgrind -qq 5 | - git clone https://github.com/clibs/clib.git /tmp/clib 6 | - sudo make -C /tmp/clib install 7 | install: clib install --dev 8 | script: 9 | - make test 10 | - valgrind --leak-check=full --error-exitcode=5 ./test > /dev/null -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | CFLAGS = -std=c99 -Wall -Wextra -Ideps 3 | SRC = ms.c 4 | DEPS = $(wildcard deps/*/*.c) 5 | OBJS = ms.o $(DEPS:.c=.o) 6 | 7 | check: test 8 | @./test 9 | 10 | test: test.o $(OBJS) 11 | $(CC) $^ -o $@ $(CFLAGS) 12 | 13 | %.o: %.c 14 | $(CC) $< -c -o $@ $(CFLAGS) 15 | 16 | clean: 17 | rm -f $(OBJS) test.o test 18 | 19 | .PHONY: check clean 20 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ms", 3 | "version": "0.0.4", 4 | "repo": "clibs/ms", 5 | "description": "String to microsecond & millisecond utilities", 6 | "keywords": ["ms", "us", "usec", "millisecond", "microsecond", "conversion", "convert"], 7 | "license": "MIT", 8 | "src": ["ms.c", "ms.h"], 9 | "dependencies": { 10 | "littlstar/asprintf.c": "0.0.3" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /ms.h: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // ms.h 4 | // 5 | // Copyright (c) 2012 TJ Holowaychuk 6 | // 7 | 8 | #ifndef MS_H 9 | #define MS_H 1 10 | 11 | // prototypes 12 | 13 | long long 14 | string_to_microseconds(const char *str); 15 | 16 | long long 17 | string_to_milliseconds(const char *str); 18 | 19 | long long 20 | string_to_seconds(const char *str); 21 | 22 | char * 23 | milliseconds_to_string(long long ms); 24 | 25 | char * 26 | milliseconds_to_long_string(long long ms); 27 | 28 | #endif // MS_H 29 | 30 | -------------------------------------------------------------------------------- /History.md: -------------------------------------------------------------------------------- 1 | 2 | 0.0.4 / 2014-07-07 3 | ================== 4 | 5 | * Add Travis 6 | * package.json: Update asprintf to 0.0.3 7 | * ms.c: Use `asprintf` to avoid possible memory overflow 8 | * ms.h: Remove MS_MAX 9 | * ms.c: Move tests into their own file 10 | * ms.h: Fix header guard 11 | 12 | 0.0.3 / 2013-01-25 13 | ================== 14 | 15 | * fix long long overflow 16 | 17 | 0.0.2 / 2013-01-25 18 | ================== 19 | 20 | * no clue 21 | 22 | 0.0.2 / 2012-09-17 23 | ================== 24 | 25 | * add `string_to_seconds(str)` 26 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | 2 | # ms 3 | 4 | Convert strings like "15s" to seconds, milliseconds, or microseconds, 5 | and convert milliseconds to strings ("300ms", "5ms") or long strings ("5 seconds", "1 month"). 6 | 7 | ## Installation 8 | 9 | Install with [clib](https://github.com/clibs/clib): 10 | 11 | ``` 12 | $ clib install clibs/ms 13 | ``` 14 | 15 | ## API 16 | 17 | ```c 18 | long long 19 | string_to_microseconds(const char *str); 20 | 21 | long long 22 | string_to_milliseconds(const char *str); 23 | 24 | long long 25 | string_to_seconds(const char *str); 26 | 27 | char * 28 | milliseconds_to_string(long long ms); 29 | 30 | char * 31 | milliseconds_to_long_string(long long ms); 32 | ``` 33 | 34 | For usage view the [tests](https://github.com/clibs/ms/blob/master/ms.c#L52) -------------------------------------------------------------------------------- /test.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "ms.h" 7 | 8 | #define LL long long 9 | 10 | void 11 | equal(char *a, char *b) { 12 | if (strcmp(a, b)) { 13 | printf("expected: %s\n", a); 14 | printf("actual: %s\n", b); 15 | free(b); 16 | exit(1); 17 | } 18 | free(b); 19 | } 20 | 21 | void 22 | test_string_to_microseconds() { 23 | assert(string_to_microseconds("") == -1); 24 | assert(string_to_microseconds("s") == -1); 25 | assert(string_to_microseconds("hey") == -1); 26 | assert(string_to_microseconds("5000") == 5000); 27 | assert(string_to_microseconds("1ms") == 1000); 28 | assert(string_to_microseconds("5ms") == 5000); 29 | assert(string_to_microseconds("1s") == 1000000); 30 | assert(string_to_microseconds("5s") == 5000000); 31 | assert(string_to_microseconds("1m") == 60000000); 32 | assert(string_to_microseconds("1h") == 3600000000); 33 | assert(string_to_microseconds("2d") == 2 * 24 * 3600000000); 34 | } 35 | 36 | void 37 | test_string_to_milliseconds() { 38 | assert(string_to_milliseconds("") == -1); 39 | assert(string_to_milliseconds("s") == -1); 40 | assert(string_to_milliseconds("hey") == -1); 41 | assert(string_to_milliseconds("5000") == 5000); 42 | assert(string_to_milliseconds("1ms") == 1); 43 | assert(string_to_milliseconds("5ms") == 5); 44 | assert(string_to_milliseconds("1s") == 1000); 45 | assert(string_to_milliseconds("5s") == 5000); 46 | assert(string_to_milliseconds("1m") == 60 * 1000); 47 | assert(string_to_milliseconds("1h") == 60 * 60 * 1000); 48 | assert(string_to_milliseconds("1d") == 24 * 60 * 60 * 1000); 49 | } 50 | 51 | void 52 | test_string_to_seconds() { 53 | assert(string_to_seconds("") == -1); 54 | assert(string_to_seconds("s") == -1); 55 | assert(string_to_seconds("hey") == -1); 56 | assert(string_to_seconds("5000") == 5); 57 | assert(string_to_seconds("1ms") == 0); 58 | assert(string_to_seconds("5ms") == 0); 59 | assert(string_to_seconds("1s") == 1); 60 | assert(string_to_seconds("5s") == 5); 61 | assert(string_to_seconds("1m") == 60); 62 | assert(string_to_seconds("1h") == 60 * 60); 63 | assert(string_to_seconds("1d") == 24 * 60 * 60); 64 | } 65 | 66 | void 67 | test_milliseconds_to_string() { 68 | equal("500ms", milliseconds_to_string(500)); 69 | equal("5s", milliseconds_to_string(5000)); 70 | equal("2s", milliseconds_to_string(2500)); 71 | equal("1m", milliseconds_to_string(60 * 1000)); 72 | equal("5m", milliseconds_to_string(5 * 60 * 1000)); 73 | equal("1h", milliseconds_to_string(60 * 60 * 1000)); 74 | equal("2d", milliseconds_to_string(2 * 24 * 60 * 60 * 1000)); 75 | equal("2w", milliseconds_to_string(15 * 24 * 60 * 60 * 1000)); 76 | equal("3y", milliseconds_to_string((LL) 3 * 52 * 7 * 24 * 60 * 60 * 1000)); 77 | } 78 | 79 | void 80 | test_milliseconds_to_long_string() { 81 | equal("less than one second", milliseconds_to_long_string(500)); 82 | equal("5 seconds", milliseconds_to_long_string(5000)); 83 | equal("2 seconds", milliseconds_to_long_string(2500)); 84 | equal("1 minute", milliseconds_to_long_string(60 * 1000)); 85 | equal("5 minutes", milliseconds_to_long_string(5 * 60 * 1000)); 86 | equal("1 hour", milliseconds_to_long_string(60 * 60 * 1000)); 87 | equal("2 days", milliseconds_to_long_string(2 * 24 * 60 * 60 * 1000)); 88 | equal("2 weeks", milliseconds_to_long_string(15 * 24 * 60 * 60 * 1000)); 89 | equal("1 year", milliseconds_to_long_string((LL) 52 * 7 * 24 * 60 * 60 * 1000)); 90 | equal("3 years", milliseconds_to_long_string((LL) 3 * 52 * 7 * 24 * 60 * 60 * 1000)); 91 | } 92 | 93 | int 94 | main(){ 95 | test_string_to_microseconds(); 96 | test_string_to_milliseconds(); 97 | test_string_to_seconds(); 98 | test_milliseconds_to_string(); 99 | test_milliseconds_to_long_string(); 100 | printf("\n \e[32m\u2713 \e[90mok\e[0m\n\n"); 101 | return 0; 102 | } 103 | -------------------------------------------------------------------------------- /ms.c: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // ms.c 4 | // 5 | // Copyright (c) 2012 TJ Holowaychuk 6 | // 7 | 8 | #include 9 | #include 10 | #include 11 | #include "asprintf/asprintf.h" 12 | #include "ms.h" 13 | 14 | // microseconds 15 | 16 | #define US_MSEC (long long) 1000 17 | #define US_SEC 1000 * US_MSEC 18 | #define US_MIN 60 * US_SEC 19 | #define US_HOUR 60 * US_MIN 20 | #define US_DAY 24 * US_HOUR 21 | #define US_WEEK 7 * US_DAY 22 | #define US_YEAR 52 * US_WEEK 23 | 24 | // milliseconds 25 | 26 | #define MS_SEC (long long)1000 27 | #define MS_MIN 60 * MS_SEC 28 | #define MS_HOUR 60 * MS_MIN 29 | #define MS_DAY 24 * MS_HOUR 30 | #define MS_WEEK 7 * MS_DAY 31 | #define MS_YEAR 52 * MS_WEEK 32 | 33 | /* 34 | * Convert the given `str` representation to microseconds, 35 | * for example "10ms", "5s", "2m", "1h" etc. 36 | */ 37 | 38 | long long 39 | string_to_microseconds(const char *str) { 40 | size_t len = strlen(str); 41 | long long val = strtoll(str, NULL, 10); 42 | if (!val) return -1; 43 | switch (str[len - 1]) { 44 | case 's': return 'm' == str[len - 2] ? val * 1000 : val * US_SEC; 45 | case 'm': return val * US_MIN; 46 | case 'h': return val * US_HOUR; 47 | case 'd': return val * US_DAY; 48 | case 'w': return val * US_WEEK; 49 | case 'y': return val * US_YEAR; 50 | default: return val; 51 | } 52 | } 53 | 54 | /* 55 | * Convert the given `str` representation to milliseconds, 56 | * for example "10ms", "5s", "2m", "1h" etc. 57 | */ 58 | 59 | long long 60 | string_to_milliseconds(const char *str) { 61 | size_t len = strlen(str); 62 | long long val = strtoll(str, NULL, 10); 63 | if (!val) return -1; 64 | switch (str[len - 1]) { 65 | case 's': return 'm' == str[len - 2] ? val : val * 1000; 66 | case 'm': return val * MS_MIN; 67 | case 'h': return val * MS_HOUR; 68 | case 'd': return val * MS_DAY; 69 | case 'w': return val * MS_WEEK; 70 | case 'y': return val * MS_YEAR; 71 | default: return val; 72 | } 73 | } 74 | 75 | /* 76 | * Convert the given `str` representation to seconds. 77 | */ 78 | 79 | long long 80 | string_to_seconds(const char *str) { 81 | long long ret = string_to_milliseconds(str); 82 | if (-1 == ret) return ret; 83 | return ret / 1000; 84 | } 85 | 86 | /* 87 | * Convert the given `ms` to a string. This 88 | * value must be `free()`d by the developer. 89 | */ 90 | 91 | char * 92 | milliseconds_to_string(long long ms) { 93 | char *str = NULL; 94 | long long div = 1; 95 | char *fmt; 96 | 97 | if (ms < MS_SEC) fmt = "%lldms"; 98 | else if (ms < MS_MIN) { fmt = "%llds"; div = MS_SEC; } 99 | else if (ms < MS_HOUR) { fmt = "%lldm"; div = MS_MIN; } 100 | else if (ms < MS_DAY) { fmt = "%lldh"; div = MS_HOUR; } 101 | else if (ms < MS_WEEK) { fmt = "%lldd"; div = MS_DAY; } 102 | else if (ms < MS_YEAR) { fmt = "%lldw"; div = MS_WEEK; } 103 | else { fmt = "%lldy"; div = MS_YEAR; } 104 | if (-1 == asprintf(&str, fmt, ms / div)) { 105 | return NULL; 106 | } 107 | 108 | return str; 109 | } 110 | 111 | /* 112 | * Convert the given `ms` to a long string. This 113 | * value must be `free()`d by the developer. 114 | */ 115 | 116 | char * 117 | milliseconds_to_long_string(long long ms) { 118 | long long div; 119 | char *name; 120 | 121 | char *str = NULL; 122 | 123 | if (ms < MS_SEC) { 124 | if (-1 == asprintf(&str, "less than one second")) return NULL; 125 | return str; 126 | } 127 | 128 | if (ms < MS_MIN) { name = "second"; div = MS_SEC; } 129 | else if (ms < MS_HOUR) { name = "minute"; div = MS_MIN; } 130 | else if (ms < MS_DAY) { name = "hour"; div = MS_HOUR; } 131 | else if (ms < MS_WEEK) { name = "day"; div = MS_DAY; } 132 | else if (ms < MS_YEAR) { name = "week"; div = MS_WEEK; } 133 | else { name = "year"; div = MS_YEAR; } 134 | 135 | long long val = ms / div; 136 | char *fmt = 1 == val 137 | ? "%lld %s" 138 | : "%lld %ss"; 139 | 140 | if (-1 == asprintf(&str, fmt, val, name)) { 141 | return NULL; 142 | } 143 | 144 | return str; 145 | } 146 | 147 | --------------------------------------------------------------------------------