From c035571d85e3d756804519d82de8b354f3910b29 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Thu, 8 Feb 2024 21:19:38 +0200 Subject: project work phase 1 --- src/date.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 src/date.c (limited to 'src/date.c') diff --git a/src/date.c b/src/date.c new file mode 100644 index 0000000..7e6bc77 --- /dev/null +++ b/src/date.c @@ -0,0 +1,72 @@ +#include + +#include + +ph_date_t date_from_string(const char str[static 11]) +{ + unsigned year = (str[0] - '0') * 1000 + + (str[1] - '0') * 100 + + (str[2] - '0') * 10 + + (str[3] - '0'); + + unsigned month = (str[5] - '0') * 10 + + (str[6] - '0'); + + unsigned day = (str[8] - '0') * 10 + + (str[9] - '0'); + + return date_from_numbers(year, month, day); +} + +ph_date_t date_from_numbers(unsigned year, unsigned month, unsigned day) +{ + return year << 9 | month << 5 | day; +} + +void date_split(ph_date_t date, unsigned *year, unsigned *month, unsigned *day) +{ + if (year) *year = date >> 9; + if (month) *month = (date >> 5) & 0xf; + if (day) *day = date & 0x1f; +} + +void date_to_string(char str[static 11], ph_date_t date) +{ + unsigned year, month, day; + date_split(date, &year, &month, &day); + + str[0] = '0' + (year / 1000) % 10; + str[1] = '0' + (year / 100) % 10; + str[2] = '0' + (year / 10) % 10; + str[3] = '0' + year % 10; + str[4] = '-'; + str[5] = '0' + (month / 10) % 10; + str[6] = '0' + month % 10; + str[7] = '-'; + str[8] = '0' + (day / 10) % 10; + str[9] = '0' + day % 10; + str[10] = '\0'; +} + +bool date_valid(ph_date_t date) +{ + unsigned year, month, day; + date_split(date, &year, &month, &day); + + struct tm tm = {0}; + tm.tm_year = year; + /* goddammit */ + tm.tm_mon = month - 1; + tm.tm_mday = day; + + time_t r = mktime(&tm); + /* if mktime fails to represent our time, it returns -1. mktime somewhat + * curiously accepts dates outside regular ranges, like negative time, + * but adjusts the tm structure to be 'correct', so we can check if any + * of the times were modified to see if this is a valid time. */ + if (r == -1 || (int)year != tm.tm_year + || (int)month != tm.tm_mon + 1|| (int)day != tm.tm_mday) + return false; + + return true; +} -- cgit v1.2.3