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

68 lines
2.1 KiB
C
Raw Normal View History

/*
* 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;
}