1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/sys/phydat/phydat_unix.c
Silke Hofstra 26653dd446 sys/phydat: add functions for Unix time conversion to phydat
Add functionality for calculating Unix timestamps to phydat.
This allows one to convert dates received from RTCs and the like
to Unix timestamps.
2023-01-21 11:01:42 +01:00

68 lines
2.1 KiB
C

/*
* Copyright (C) 2023 Silke Hofstra
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
#include <stdint.h>
#include <math.h>
#include "phydat.h"
/**
* Offsets of the first day of the month starting with January.
* Months after February have a negative offset to efficiently handle leap years.
*/
static int16_t month_to_yday[] = { 0, 31, -306, -275, -245, -214,
-184, -153, -122, -92, -61, -31 };
static inline int16_t phydat_unscale(int16_t value, int16_t scale)
{
if (scale > 0) {
return value * pow(10, scale);
}
if (scale < 0) {
return value / pow(10, -scale);
}
return value;
}
int64_t phydat_date_time_to_unix(phydat_t *date, phydat_t *time, int32_t offset_seconds)
{
return phydat_unix(
phydat_unscale(date->val[2], date->scale),
phydat_unscale(date->val[1], date->scale),
phydat_unscale(date->val[0], date->scale),
phydat_unscale(time->val[2], time->scale),
phydat_unscale(time->val[1], time->scale),
phydat_unscale(time->val[0], time->scale),
offset_seconds);
}
int64_t phydat_unix(int16_t year, int16_t month, int16_t day,
int16_t hour, int16_t minute, int16_t second,
int32_t offset_seconds)
{
/* Make the year relative to 1900. */
/* Add a year for months after Feb to deal with leap years. */
year += (month > 2 ? 1 : 0) - 1900;
/* Calculate the day of the year based on the month */
day += month_to_yday[(month - 1) % 12] - 1;
/* POSIX calculation of a UNIX timestamp. */
/* See section 4.16 of The Open Group Base Specifications Issue 7. */
int16_t leap_days = ((year - 69) / 4) - ((year - 1) / 100) + ((year + 299) / 400);
return (int64_t)(day + leap_days) * 86400 +
(int64_t)(year - 70) * 31536000 +
(int64_t)(hour) * 3600 +
(int64_t)(minute) * 60 +
(int64_t)(second) -
offset_seconds;
}