mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
26653dd446
Add functionality for calculating Unix timestamps to phydat. This allows one to convert dates received from RTCs and the like to Unix timestamps.
68 lines
2.1 KiB
C
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;
|
|
}
|