mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
periph_common/rtc: add rtc_mktime()
Add a function to convert a time struct to an unsigned timestamp (non-UNIX).
This commit is contained in:
parent
6dd69e7134
commit
becff61e20
@ -37,6 +37,7 @@
|
||||
#ifndef PERIPH_RTC_H
|
||||
#define PERIPH_RTC_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
#include "periph_conf.h"
|
||||
|
||||
@ -147,6 +148,19 @@ void rtc_tm_normalize(struct tm *time);
|
||||
*/
|
||||
int rtc_tm_compare(const struct tm *a, const struct tm *b);
|
||||
|
||||
/**
|
||||
* @brief Convert time struct into timestamp.
|
||||
*
|
||||
* @pre The time structs @p a and @p b are assumed to be normalized.
|
||||
* Use @ref rtc_tm_normalize to normalize a struct tm that has been
|
||||
* manually edited.
|
||||
*
|
||||
* @param[in] t The time struct to convert
|
||||
*
|
||||
* @return elapsed seconds since `RIOT_EPOCH`
|
||||
*/
|
||||
uint32_t rtc_mktime(struct tm *t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -26,6 +26,14 @@
|
||||
#define RTC_NORMALIZE_COMPAT (0)
|
||||
#endif
|
||||
|
||||
#define MINUTE (60U)
|
||||
#define HOUR (60U * MINUTE)
|
||||
#define DAY (24U * HOUR)
|
||||
|
||||
#ifndef RIOT_EPOCH
|
||||
#define RIOT_EPOCH (2020)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The rules here are (to be checked in that explicit order):
|
||||
* 1. If the year is not a multiple of four, it is not a leap year.
|
||||
@ -52,6 +60,26 @@ static int _is_leap_year(int year)
|
||||
return !!(year % 25) || !(year & 15);
|
||||
}
|
||||
|
||||
/*
|
||||
* 1. Every fourth year was a leap year.
|
||||
* 2. Subtract all years divisible by 100, those are divisible by 4 but no leap years.
|
||||
* 3. Add back all years divisible by 400, those are divisible by 100 but leap years.
|
||||
*/
|
||||
static unsigned _leap_years_before(unsigned year)
|
||||
{
|
||||
--year;
|
||||
return (year / 4) - (year / 100) + (year / 400);
|
||||
}
|
||||
|
||||
static unsigned _leap_years_since_epoch(unsigned year)
|
||||
{
|
||||
if (year < RIOT_EPOCH) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _leap_years_before(year) - _leap_years_before(RIOT_EPOCH);
|
||||
}
|
||||
|
||||
static int _month_length(int month, int year)
|
||||
{
|
||||
if (month == 1) {
|
||||
@ -81,6 +109,7 @@ static int _wday(int day, int month, int year)
|
||||
year -= month < 2;
|
||||
return (year + year/4 - year/100 + year/400 + t[month] + day) % 7;
|
||||
}
|
||||
#endif /* RTC_NORMALIZE_COMPAT */
|
||||
|
||||
static int _yday(int day, int month, int year)
|
||||
{
|
||||
@ -104,7 +133,6 @@ static int _yday(int day, int month, int year)
|
||||
2019-01-01 will be be day 0 in year 2019 */
|
||||
return d[month] + day - 1;
|
||||
}
|
||||
#endif /* RTC_NORMALIZE_COMPAT */
|
||||
|
||||
void rtc_tm_normalize(struct tm *t)
|
||||
{
|
||||
@ -148,6 +176,22 @@ void rtc_tm_normalize(struct tm *t)
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t rtc_mktime(struct tm *t)
|
||||
{
|
||||
unsigned year = t->tm_year + 1900;
|
||||
uint32_t time = t->tm_sec
|
||||
+ t->tm_min * MINUTE
|
||||
+ t->tm_hour * HOUR
|
||||
+ _yday(t->tm_mday, t->tm_mon, year) * DAY;
|
||||
|
||||
unsigned leap_years = _leap_years_since_epoch(year);
|
||||
unsigned common_years = (year - RIOT_EPOCH) - leap_years;
|
||||
|
||||
time += (leap_years * 366 + common_years * 365) * DAY;
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
#define RETURN_IF_DIFFERENT(a, b, member) \
|
||||
if (a->member != b->member) { \
|
||||
return a->member-b->member; \
|
||||
|
@ -199,6 +199,31 @@ static void test_rtc_compare(void)
|
||||
TEST_ASSERT(rtc_tm_compare(&t1, &t2) < 0);
|
||||
}
|
||||
|
||||
static void test_rtc_mktime(void)
|
||||
{
|
||||
struct tm t = {
|
||||
.tm_sec = 11,
|
||||
.tm_min = 12,
|
||||
.tm_hour = 13,
|
||||
.tm_mday = 1,
|
||||
.tm_mon = 0,
|
||||
.tm_year = 120,
|
||||
.tm_wday = 0,
|
||||
.tm_yday = 1,
|
||||
};
|
||||
|
||||
mktime(&t);
|
||||
TEST_ASSERT_EQUAL_INT(47531, rtc_mktime(&t));
|
||||
|
||||
t.tm_mday += 40;
|
||||
mktime(&t);
|
||||
TEST_ASSERT_EQUAL_INT(3503531, rtc_mktime(&t));
|
||||
|
||||
t.tm_year += 3;
|
||||
mktime(&t);
|
||||
TEST_ASSERT_EQUAL_INT(98197931, rtc_mktime(&t));
|
||||
}
|
||||
|
||||
Test *tests_rtc_tests(void)
|
||||
{
|
||||
EMB_UNIT_TESTFIXTURES(fixtures) {
|
||||
@ -209,6 +234,7 @@ Test *tests_rtc_tests(void)
|
||||
new_TestFixture(test_rtc_ywrap),
|
||||
new_TestFixture(test_rtc_year),
|
||||
new_TestFixture(test_rtc_compare),
|
||||
new_TestFixture(test_rtc_mktime),
|
||||
};
|
||||
|
||||
EMB_UNIT_TESTCALLER(rtc_tests, NULL, NULL, fixtures);
|
||||
|
Loading…
Reference in New Issue
Block a user