mirror of
https://github.com/joeycastillo/utz.git
synced 2026-04-27 17:24:11 +00:00
Fix warnings / compiler errors for SDCC, add Arduino library file
This commit is contained in:
9
library.properties
Normal file
9
library.properties
Normal file
@ -0,0 +1,9 @@
|
||||
name=micro timezone library
|
||||
version=0.0.1
|
||||
author=eV
|
||||
maintainer=eV <eV@7pr.xyz.com>
|
||||
sentence=This is a C library for handling timezones
|
||||
paragraph=This is a C library for handling timezones
|
||||
category=Time
|
||||
url=https://github.com/evq/utz
|
||||
architectures=*
|
||||
@ -382,7 +382,7 @@ class TimeZoneDatabase(object):
|
||||
char.append('\\0')
|
||||
total_char += len(char) + 1
|
||||
buf.append("%80s, %3d, // %s" % ("'%s'" % "','".join(char), index, name))
|
||||
buf[buf.index('PLACEHOLDER')] = 'char zone_names[%d] = {' % total_char
|
||||
buf[buf.index('PLACEHOLDER')] = 'unsigned char zone_names[%d] = {' % total_char
|
||||
buf.append('};')
|
||||
buf.append('')
|
||||
buf.append('#define NUM_ZONE_NAMES %d' % len(aliases))
|
||||
|
||||
132
utz.c
132
utz.c
@ -4,24 +4,43 @@
|
||||
* @author eV
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "utz.h"
|
||||
#include "zones.h"
|
||||
|
||||
static uint8_t ustrneq(char* string1, char* string2, uint8_t n) {
|
||||
uint8_t i;
|
||||
for (i = 0; i < n && string1[i] != '\0' && string2[i] != '\0'; i++) {
|
||||
if (string1[i] != string2[i]) {
|
||||
return UFALSE;
|
||||
}
|
||||
}
|
||||
return UTRUE;
|
||||
}
|
||||
|
||||
static char* ustrncpy(char* dest, char* src, uint8_t n) {
|
||||
uint8_t i;
|
||||
for (i = 0; i < n; i++) {
|
||||
dest[i] = src[i];
|
||||
if (src[i] == '\0') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
void bin_to_bcd(uint32_t* raw) {
|
||||
uint8_t i;
|
||||
uint8_t* ptr = (uint8_t*) raw;
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
ptr[i] = ((ptr[i] / 10) << 4) | (ptr[i] % 10);
|
||||
}
|
||||
}
|
||||
void bcd_to_bin(uint32_t* raw) {
|
||||
uint8_t i;
|
||||
uint8_t* ptr = (uint8_t*) raw;
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
ptr[i] = (ptr[i] & 0x0F) + ((ptr[i] >> 4) * 10);
|
||||
}
|
||||
}
|
||||
@ -35,9 +54,9 @@ uint8_t dayofweek(uint8_t y, uint8_t m, uint8_t d) {
|
||||
|
||||
uint8_t is_leap_year(uint8_t y) {
|
||||
if ((((UYEAR_TO_YEAR(y) % 4) == 0) && ((UYEAR_TO_YEAR(y) % 100) != 0)) || ((UYEAR_TO_YEAR(y) % 400) == 0)) {
|
||||
return true;
|
||||
return UTRUE;
|
||||
}
|
||||
return false;
|
||||
return UFALSE;
|
||||
}
|
||||
|
||||
uint8_t days_in_month(uint8_t y, uint8_t m) {
|
||||
@ -72,31 +91,25 @@ uint8_t udatetime_ge(udatetime_t* dt1, udatetime_t* dt2) {
|
||||
(dt1->date.raw == dt2->date.raw && dt1->time.raw >= dt2->time.raw));
|
||||
}
|
||||
|
||||
uint8_t next_packed_zone(char** list) {
|
||||
while(1) {
|
||||
if (*(*list) == '\0') {
|
||||
(*list)++;
|
||||
return (uint8_t) *(*list)++;
|
||||
}
|
||||
(*list)++;
|
||||
}
|
||||
}
|
||||
|
||||
void unpack_rule(urule_packed_t* rule_in, uint8_t cur_year, urule_t* rule_out) {
|
||||
uint8_t dayofweek_of_first_dayofmonth;
|
||||
uint8_t first_dayofweek;
|
||||
uint8_t dayofweek_of_dayofmonth;
|
||||
|
||||
rule_out->date.year = cur_year;
|
||||
rule_out->date.month = rule_in->in_month;
|
||||
|
||||
if (rule_in->on_dayofweek == 0) { // format is DOM e.g. 22
|
||||
rule_out->date.dayofmonth = rule_in->on_dayofmonth;
|
||||
} else if (rule_in->on_dayofmonth == 0) { // format is lastDOW e.g. lastSun
|
||||
uint8_t dayofweek_of_first_dayofmonth = dayofweek(cur_year, rule_in->in_month, 1);
|
||||
uint8_t first_dayofweek = next_dayofweek_offset(dayofweek_of_first_dayofmonth, rule_in->on_dayofweek);
|
||||
dayofweek_of_first_dayofmonth = dayofweek(cur_year, rule_in->in_month, 1);
|
||||
first_dayofweek = next_dayofweek_offset(dayofweek_of_first_dayofmonth, rule_in->on_dayofweek);
|
||||
rule_out->date.dayofmonth = 1 + (7*3) + first_dayofweek;
|
||||
if (rule_out->date.dayofmonth + 7 <= days_in_month(cur_year, rule_in->in_month)) {
|
||||
rule_out->date.dayofmonth += 7;
|
||||
}
|
||||
} else { // format is DOW >= DOM e.g. Sun>=22
|
||||
uint8_t dayofweek_of_dayofmonth = dayofweek(cur_year, rule_in->in_month, rule_in->on_dayofmonth);
|
||||
dayofweek_of_dayofmonth = dayofweek(cur_year, rule_in->in_month, rule_in->on_dayofmonth);
|
||||
rule_out->date.dayofmonth = rule_in->on_dayofmonth + next_dayofweek_offset(
|
||||
dayofweek_of_dayofmonth,
|
||||
rule_in->on_dayofweek
|
||||
@ -109,10 +122,10 @@ void unpack_rule(urule_packed_t* rule_in, uint8_t cur_year, urule_t* rule_out) {
|
||||
rule_out->is_local_time = rule_in->at_is_local_time;
|
||||
switch(rule_in->letter) {
|
||||
case S:
|
||||
rule_out->letter = 's';
|
||||
rule_out->letter = 'S';
|
||||
break;
|
||||
case D:
|
||||
rule_out->letter = 'd';
|
||||
rule_out->letter = 'D';
|
||||
break;
|
||||
default:
|
||||
rule_out->letter = '-';
|
||||
@ -121,31 +134,40 @@ void unpack_rule(urule_packed_t* rule_in, uint8_t cur_year, urule_t* rule_out) {
|
||||
rule_out->offset_hours = rule_in->offset_hours;
|
||||
}
|
||||
|
||||
// assumes no two rules are active on the same day
|
||||
static void rulecpy(urule_t* dest, urule_t* src) {
|
||||
dest->time.raw = src->time.raw;
|
||||
dest->date.raw = src->date.raw;
|
||||
dest->is_local_time = src->is_local_time;
|
||||
dest->letter = src->letter;
|
||||
dest->offset_hours = src->offset_hours;
|
||||
}
|
||||
|
||||
void sort_rules(urule_t* rules, uint8_t num_rules) {
|
||||
uint8_t swapped = true;
|
||||
uint8_t i;
|
||||
uint8_t swapped = UTRUE;
|
||||
urule_t tmp_current_rule;
|
||||
|
||||
while(swapped) {
|
||||
swapped = false;
|
||||
for (uint8_t i = 1; i < num_rules; i++) {
|
||||
swapped = UFALSE;
|
||||
for (i = 1; i < num_rules; i++) {
|
||||
if (rules[i-1].date.raw > rules[i].date.raw) {
|
||||
tmp_current_rule = rules[i-1];
|
||||
rules[i-1] = rules[i];
|
||||
rules[i] = tmp_current_rule;
|
||||
swapped = true;
|
||||
rulecpy(&tmp_current_rule, &rules[i-1]);
|
||||
rulecpy(&rules[i-1], &rules[i]);
|
||||
rulecpy(&rules[i], &tmp_current_rule);
|
||||
swapped = UTRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void unpack_rules(urule_packed_t* rules_in, uint8_t num_rules, uint8_t cur_year, urule_t* rules_out) {
|
||||
uint8_t i = 0;
|
||||
int8_t l = 0;
|
||||
uint8_t current_rule_count = 0;
|
||||
|
||||
// First lets find the "last" rule of the previous year, for simplification
|
||||
// this assumes that multiple rules don't apply to the same month
|
||||
int8_t l = 0;
|
||||
for (uint8_t i = 1; i < num_rules; i++) {
|
||||
for (i = 1; i < num_rules; i++) {
|
||||
if (cur_year - 1 >= rules_in[i].from_year && cur_year - 1 <= rules_in[i].to_year) {
|
||||
if (rules_in[i].in_month > rules_in[l].in_month) {
|
||||
l = i;
|
||||
@ -161,7 +183,7 @@ void unpack_rules(urule_packed_t* rules_in, uint8_t num_rules, uint8_t cur_year,
|
||||
rules_out[current_rule_count].time.raw = 0;
|
||||
current_rule_count++;
|
||||
|
||||
for (uint8_t i = 0; i < num_rules && current_rule_count < MAX_CURRENT_RULES; i++) {
|
||||
for (i = 0; i < num_rules && current_rule_count < MAX_CURRENT_RULES; i++) {
|
||||
if (cur_year >= rules_in[i].from_year && cur_year <= rules_in[i].to_year) {
|
||||
unpack_rule(&rules_in[i], cur_year, &rules_out[current_rule_count++]);
|
||||
}
|
||||
@ -171,7 +193,8 @@ void unpack_rules(urule_packed_t* rules_in, uint8_t num_rules, uint8_t cur_year,
|
||||
}
|
||||
|
||||
urule_t* get_active_rule(urule_t* rules, udatetime_t* datetime) {
|
||||
for (uint8_t i = 1; i < MAX_CURRENT_RULES; i++) {
|
||||
int8_t i = 0;
|
||||
for (i = 1; i < MAX_CURRENT_RULES; i++) {
|
||||
if (!RULE_IS_VALID(rules[i]) || udatetime_lt(datetime, &(rules[i].datetime))) {
|
||||
return &rules[i-1];
|
||||
}
|
||||
@ -179,25 +202,52 @@ urule_t* get_active_rule(urule_t* rules, udatetime_t* datetime) {
|
||||
return &rules[MAX_CURRENT_RULES-1];
|
||||
}
|
||||
|
||||
uoffset_t get_current_offset(uzone_t* zone, udatetime_t* datetime) {
|
||||
char get_current_offset(uzone_t* zone, udatetime_t* datetime, uoffset_t* offset) {
|
||||
urule_t* rule;
|
||||
if (last_zone != zone->src || last_year != datetime->date.year) {
|
||||
unpack_rules(zone->rules, zone->rules_len, datetime->date.year, cached_rules);
|
||||
last_zone = zone->src;
|
||||
last_year = datetime->date.year;
|
||||
}
|
||||
|
||||
uoffset_t offset = zone->offset;
|
||||
offset.hours += get_active_rule(cached_rules, datetime)->offset_hours;
|
||||
return offset;
|
||||
offset->minutes = zone->offset.minutes;
|
||||
offset->hours = zone->offset.hours;
|
||||
rule = get_active_rule(cached_rules, datetime);
|
||||
offset->hours += rule->offset_hours;
|
||||
return rule->letter;
|
||||
}
|
||||
|
||||
void unpack_zone(uzone_packed_t* zone_in, char* name, uzone_t* zone_out) {
|
||||
zone_out->src = zone_in;
|
||||
strncpy(zone_out->name, name, MAX_ZONE_NAME_LEN);
|
||||
ustrncpy(zone_out->name, name, MAX_ZONE_NAME_LEN);
|
||||
|
||||
zone_out->offset.minutes = (zone_in->offset_inc_minutes % (60 / OFFSET_INCREMENT)) * OFFSET_INCREMENT;
|
||||
zone_out->offset.hours = zone_in->offset_inc_minutes / (60 / OFFSET_INCREMENT);
|
||||
zone_out->rules = &zone_rules[zone_in->rules_idx];
|
||||
zone_out->rules_len = zone_in->rules_len;
|
||||
strncpy(zone_out->abrev_formatter, zone_in->abrev_formatter, MAX_ABREV_FORMATTER_LEN);
|
||||
ustrncpy(zone_out->abrev_formatter, zone_in->abrev_formatter, MAX_ABREV_FORMATTER_LEN);
|
||||
}
|
||||
|
||||
uint8_t next_packed_zone(char** list) {
|
||||
while(1) {
|
||||
if (*(*list) == '\0') {
|
||||
(*list)++;
|
||||
return (uint8_t) *(*list)++;
|
||||
}
|
||||
(*list)++;
|
||||
}
|
||||
}
|
||||
|
||||
void get_zone_by_name(char* name, uzone_t* zone_out) {
|
||||
uint16_t i;
|
||||
uint8_t zone_idx = 0;
|
||||
char* zone = zone_names;
|
||||
for (i = 0; i < NUM_ZONE_NAMES; i++) {
|
||||
if (ustrneq(zone, name, MAX_ZONE_NAME_LEN)) {
|
||||
unpack_zone(&zone_defns[next_packed_zone(&zone)], name, zone_out);
|
||||
break;
|
||||
} else {
|
||||
next_packed_zone(&zone);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
336
utz.h
336
utz.h
@ -3,9 +3,13 @@
|
||||
*
|
||||
* @author eV
|
||||
*/
|
||||
|
||||
#ifndef _UTZ_H
|
||||
#define _UTZ_H
|
||||
|
||||
#define UTRUE 1
|
||||
#define UFALSE 0
|
||||
|
||||
#define UYEAR_OFFSET 2000
|
||||
#define UYEAR_FROM_YEAR(y) (y - UYEAR_OFFSET)
|
||||
#define UYEAR_TO_YEAR(y) (y + UYEAR_OFFSET)
|
||||
@ -21,32 +25,47 @@
|
||||
#define S 1
|
||||
#define D 2
|
||||
|
||||
// Struct definitions
|
||||
/**************************************************************************/
|
||||
/* struct definitions */
|
||||
/**************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief time type
|
||||
// reverse for big endian comparisons via raw?
|
||||
/** @struct utime_t
|
||||
* @brief time type
|
||||
*
|
||||
* @var utime_t::second 0-59 or 0-0x59 in bcd mode
|
||||
* @var utime_t::minute 0-59 or 0-0x59 in bcd mode
|
||||
* @var utime_t::hour 0-23 or 0-0x23 in bcd mode
|
||||
* @var utime_t::padding unused space to pad to 4 bytes
|
||||
* @var utime_t::raw for comparisons and conversions
|
||||
*/
|
||||
typedef struct utime_t {
|
||||
union {
|
||||
struct {
|
||||
// reverse for big endian comparisons via raw?
|
||||
uint8_t second; // 0-59 or 0-0x59 in bcd mode
|
||||
uint8_t minute; // 0-59 or 0-0x59 in bcd mode
|
||||
uint8_t hour; // 0-23 or 0-0x23 in bcd mode
|
||||
uint8_t padding; // unused space to pad to 4 bytes
|
||||
uint8_t second;
|
||||
uint8_t minute;
|
||||
uint8_t hour;
|
||||
uint8_t padding;
|
||||
};
|
||||
uint32_t raw; // raw field for comparisons and conversions
|
||||
uint32_t raw;
|
||||
};
|
||||
} utime_t;
|
||||
|
||||
/**
|
||||
* @brief date type
|
||||
// reverse for big endian comparisons via raw?
|
||||
/** @struct udate_t
|
||||
* @brief date type
|
||||
*
|
||||
* @var udate_t::dayofweek day of week (monday = 1, sunday = 7)
|
||||
* @var udate_t::dayofmonth 01-31 or 0x01-0x31 in bcd mode
|
||||
* @var udate_t::month 01-12 or 0x01-0x12 in bcd mode
|
||||
* @var udate_t::year 00-99 or 0x00-0x99 in bcd mode
|
||||
* @var udate_t::padding unused space to pad to 4 bytes
|
||||
* @var udate_t::raw for comparisons and conversions
|
||||
*/
|
||||
typedef struct udate_t {
|
||||
uint8_t dayofweek; // day of week (monday = 1, sunday = 7)
|
||||
uint8_t dayofweek;
|
||||
union {
|
||||
struct {
|
||||
// reverse for big endian comparisons via raw?
|
||||
uint8_t dayofmonth; // 01-31 or 0x01-0x31 in bcd mode
|
||||
uint8_t month; // 01-12 or 0x01-0x12 in bcd mode
|
||||
uint8_t year; // 00-99 or 0x00-0x99 in bcd mode (offset 2000 ???)
|
||||
@ -57,69 +76,76 @@ typedef struct udate_t {
|
||||
} udate_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief datetime type
|
||||
*/
|
||||
/** @brief datetime type */
|
||||
typedef struct udatetime_t {
|
||||
utime_t time;
|
||||
udate_t date;
|
||||
} udatetime_t;
|
||||
|
||||
/**
|
||||
* @brief timezone offset type
|
||||
*/
|
||||
/** @brief timezone offset type */
|
||||
typedef struct uoffset_t {
|
||||
uint8_t minutes; // 0 to 59
|
||||
int8_t hours; // -12 to +12
|
||||
} uoffset_t;
|
||||
|
||||
/**
|
||||
* @brief packed timezone type
|
||||
/** @struct uzone_packed_t
|
||||
* @brief packed timezone type
|
||||
*
|
||||
* @var uzone_packed_t::offset_inc_minutes signed minutes in increments of OFFSET_INCREMENT
|
||||
* @var uzone_packed_t::rules_idx index into rules array for start of corresponding rules
|
||||
* @var uzone_packed_t::rules_len number of rule entries
|
||||
* @var uzone_packed_t::abrev_formatter abreviation formatter
|
||||
*/
|
||||
typedef struct uzone_packed_t {
|
||||
int8_t offset_inc_minutes; // signed OFFSET_INCREMENT minute increments
|
||||
uint8_t rules_idx; // index into rules array for start of corresponding rules
|
||||
uint8_t rules_len; // number of rule entries
|
||||
char abrev_formatter[MAX_ABREV_FORMATTER_LEN]; // abreviation formatter
|
||||
int8_t offset_inc_minutes;
|
||||
uint8_t rules_idx;
|
||||
uint8_t rules_len;
|
||||
char abrev_formatter[MAX_ABREV_FORMATTER_LEN];
|
||||
} uzone_packed_t;
|
||||
|
||||
/**
|
||||
* @brief packed rule type, rules for daylight savings time
|
||||
/** @struct urule_packed_t
|
||||
* @brief packed rule type, rules for daylight savings time
|
||||
*
|
||||
* There are 3 possible formats for on - the specifier for the day when the rule takes effect:
|
||||
* 1) the default format is "dayOfWeek >= dayOfMonth"
|
||||
* 2) unless on_dayofweek is 0, in which case the format is "dayOfMonth"
|
||||
* 3) unless on_dayofmonth is 0, in which case the format is "last dayOfWeek"
|
||||
*
|
||||
* @var urule_packed_t::from_year years since 2000
|
||||
* @var urule_packed_t::to_year years since 2000
|
||||
* @var urule_packed_t::on_dayofweek day of week (monday = 1, sunday = 7)
|
||||
* @var urule_packed_t::on_dayofmonth day of month
|
||||
* @var urule_packed_t::at_is_local_time is time of day in local time, if not utc
|
||||
* @var urule_packed_t::at_hours time of day, hours
|
||||
* @var urule_packed_t::at_inc_minutes time of day, minutes, in OFFSET_INCREMENT minute increments
|
||||
* @var urule_packed_t::letter (-,S,D) sorry Troll, Antarctica
|
||||
* @var urule_packed_t::in_month month (1-12)
|
||||
* @var urule_packed_t::offset_hours (0-3)
|
||||
*/
|
||||
typedef struct urule_packed_t {
|
||||
uint8_t from_year; // years since 2000
|
||||
uint8_t to_year; // years since 2000
|
||||
|
||||
// assume the default format is "dayOfWeek >= dayOfMonth"
|
||||
// unless on_dayofweek is 0, in which case assume format is "dayOfMonth"
|
||||
// unless on_dayofmonth is 0, in which case assume format is "last dayOfWeek"
|
||||
uint8_t on_dayofweek:3; // day of week (monday = 1, sunday = 7)
|
||||
uint8_t on_dayofmonth:5; // day of month
|
||||
|
||||
uint8_t at_is_local_time:1; // time of day, zone (UTC, LOCAL)
|
||||
uint8_t at_hours:5; // time of day, hours
|
||||
uint8_t at_inc_minutes:2; // time of day, minutes, in OFFSET_INCREMENT minute increments
|
||||
|
||||
uint8_t letter:2; // (-,S,D) sorry Troll, Antarctica
|
||||
uint8_t in_month:4; // month
|
||||
uint8_t offset_hours:2; // (0-3)
|
||||
uint8_t from_year;
|
||||
uint8_t to_year;
|
||||
uint8_t on_dayofweek:3;
|
||||
uint8_t on_dayofmonth:5;
|
||||
uint8_t at_is_local_time:1;
|
||||
uint8_t at_hours:5;
|
||||
uint8_t at_inc_minutes:2;
|
||||
uint8_t letter:2;
|
||||
uint8_t in_month:4;
|
||||
uint8_t offset_hours:2;
|
||||
} urule_packed_t;
|
||||
|
||||
/**
|
||||
* @brief unpacked zone type
|
||||
*/
|
||||
/** @brief unpacked zone type */
|
||||
typedef struct uzone_t {
|
||||
char name[MAX_ZONE_NAME_LEN+1];
|
||||
uoffset_t offset;
|
||||
urule_packed_t* rules;
|
||||
uint8_t rules_len; // number of rule entries
|
||||
uint8_t rules_len;
|
||||
char abrev_formatter[MAX_ABREV_FORMATTER_LEN+1];
|
||||
uzone_packed_t* src;
|
||||
} uzone_t;
|
||||
|
||||
/**
|
||||
* @brief unpacked rule type, rules for daylight savings time
|
||||
*/
|
||||
/** @brief unpacked rule type, rules for daylight savings time */
|
||||
typedef struct urule_t {
|
||||
union {
|
||||
udatetime_t datetime;
|
||||
@ -128,199 +154,187 @@ typedef struct urule_t {
|
||||
udate_t date;
|
||||
};
|
||||
};
|
||||
uint8_t is_local_time; // default (false) is UTC
|
||||
uint8_t is_local_time;
|
||||
char letter;
|
||||
uint8_t offset_hours;
|
||||
} urule_t;
|
||||
|
||||
// globals
|
||||
/**************************************************************************/
|
||||
/* globals */
|
||||
/**************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief lookup table for the number of days in a given month when the year is not a leap year
|
||||
*/
|
||||
/** @brief lookup table for the number of days in a given month when the year is not a leap year */
|
||||
static uint8_t days_in_month_nonleap[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
||||
|
||||
/**
|
||||
* @brief lookup table name of the days of week
|
||||
*/
|
||||
/** @brief lookup table name of the days of week */
|
||||
static char* days_of_week[8] = {"0", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
|
||||
|
||||
/**
|
||||
* @brief cached rules for the zone and year from the last call of get_current_offset
|
||||
*/
|
||||
urule_t cached_rules[MAX_CURRENT_RULES] = {0};
|
||||
/** @brief cached rules for the zone and year from the last call of get_current_offset */
|
||||
static urule_t cached_rules[MAX_CURRENT_RULES];
|
||||
|
||||
/**
|
||||
* @brief the zone pointer from the last call of get_current_offset
|
||||
*/
|
||||
uzone_packed_t* last_zone = 0;
|
||||
/** @brief the zone pointer from the last call of get_current_offset */
|
||||
static uzone_packed_t* last_zone = 0;
|
||||
|
||||
/**
|
||||
* @brief the year (1 <= y <= 255 (2001 - 2255)) from the last call of get_current_offset
|
||||
*/
|
||||
uint8_t last_year = 0;
|
||||
/** @brief the year (1 <= y <= 255 (2001 - 2255)) from the last call of get_current_offset */
|
||||
static uint8_t last_year = 0;
|
||||
|
||||
// datetime functions
|
||||
/**************************************************************************/
|
||||
/* datetime functions */
|
||||
/**************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief convert a binary formatted udate_t or utime_t to bcd format via a pointer to the raw field
|
||||
/** @brief convert a binary formatted udate_t or utime_t to bcd format via a pointer to the raw field
|
||||
*
|
||||
* @param pointer to the raw field of a udate_t or utime_t
|
||||
* @return void
|
||||
* @param pointer to the raw field of a udate_t or utime_t
|
||||
* @return void
|
||||
*/
|
||||
void bin_to_bcd(uint32_t* raw);
|
||||
|
||||
/**
|
||||
* @brief convert a bcd formatted udate_t or utime_t to binary format via a pointer to the raw field
|
||||
/** @brief convert a bcd formatted udate_t or utime_t to binary format via a pointer to the raw field
|
||||
*
|
||||
* @param pointer to the raw field of a udate_t or utime_t
|
||||
* @return void
|
||||
* @param pointer to the raw field of a udate_t or utime_t
|
||||
* @return void
|
||||
*/
|
||||
void bcd_to_bin(uint32_t* raw);
|
||||
|
||||
/**
|
||||
* @brief returns the day of the week for the given year/month/day
|
||||
/** @brief returns the day of the week for the given year/month/day
|
||||
*
|
||||
* @param y year: 1 <= y <= 255 (2001 - 2255)
|
||||
* @param m month: 1 <= m <= 12
|
||||
* @param d day: 1 <= d <= 31
|
||||
* @return day of week (Monday = 1, Sunday = 7)
|
||||
* @param y year: 1 <= y <= 255 (2001 - 2255)
|
||||
* @param m month: 1 <= m <= 12
|
||||
* @param d day: 1 <= d <= 31
|
||||
* @return day of week (Monday = 1, Sunday = 7)
|
||||
*/
|
||||
uint8_t dayofweek(uint8_t y, uint8_t m, uint8_t d);
|
||||
|
||||
/**
|
||||
* @brief returns true if the year is a leap year
|
||||
/** @brief returns true if the year is a leap year
|
||||
*
|
||||
* @param y year: 1 <= y <= 255 (2001 - 2255)
|
||||
* @brief true if the year is a leap year
|
||||
* @param y year: 1 <= y <= 255 (2001 - 2255)
|
||||
* @brief true if the year is a leap year
|
||||
*/
|
||||
uint8_t is_leap_year(uint8_t y);
|
||||
|
||||
/**
|
||||
* @brief returns the number of days in the year/month, taking leap years into account
|
||||
/** @brief returns the number of days in the year/month, taking leap years into account
|
||||
*
|
||||
* @param y year: 1 <= y <= 255 (2001 - 2255)
|
||||
* @param m month: 1 <= m <= 12
|
||||
* @return number of days
|
||||
* @param y year: 1 <= y <= 255 (2001 - 2255)
|
||||
* @param m month: 1 <= m <= 12
|
||||
* @return number of days
|
||||
*/
|
||||
uint8_t days_in_month(uint8_t y, uint8_t m);
|
||||
|
||||
/**
|
||||
* @brief returns number of days that one would need to add to the "current" day to get
|
||||
* the desired day of the week.
|
||||
/** @brief returns days needed to get from the "current" day to the desired day of the week.
|
||||
*
|
||||
* @param dayofweek_of_cur the "current" day of the week: 1 <= dayofweek_of_cur <= 7 (Monday = 1, Sunday = 7)
|
||||
* @param dayofweek the desired day of the week: 1 <= dayofweek <= 7 (Monday = 1, Sunday = 7)
|
||||
* @return number of days
|
||||
* @param dayofweek_of_cur the "current" day of the week: 1 <= dayofweek_of_cur <= 7 (Monday = 1, Sunday = 7)
|
||||
* @param dayofweek the desired day of the week: 1 <= dayofweek <= 7 (Monday = 1, Sunday = 7)
|
||||
* @return number of days
|
||||
*/
|
||||
uint8_t next_dayofweek_offset(uint8_t dayofweek_of_cur, uint8_t dayofweek);
|
||||
|
||||
/**
|
||||
* @brief returns *dt1 == *dt2
|
||||
/** @brief returns *dt1 == *dt2
|
||||
*
|
||||
* @param dt1 pointer to the first datetime
|
||||
* @param dt1 pointer to the second datetime
|
||||
* @return *dt1 == *dt2
|
||||
* @param dt1 pointer to the first datetime
|
||||
* @param dt1 pointer to the second datetime
|
||||
* @return *dt1 == *dt2
|
||||
*/
|
||||
uint8_t udatetime_eq(udatetime_t* dt1, udatetime_t* dt2);
|
||||
|
||||
/**
|
||||
* @brief returns *dt1 < *dt2
|
||||
/** @brief returns *dt1 < *dt2
|
||||
*
|
||||
* @param dt1 pointer to the first datetime
|
||||
* @param dt1 pointer to the second datetime
|
||||
* @return *dt1 < *dt2
|
||||
* @param dt1 pointer to the first datetime
|
||||
* @param dt1 pointer to the second datetime
|
||||
* @return *dt1 < *dt2
|
||||
*/
|
||||
uint8_t udatetime_lt(udatetime_t* dt1, udatetime_t* dt2);
|
||||
|
||||
/**
|
||||
* @brief returns *dt1 <= *dt2
|
||||
/** @brief returns *dt1 <= *dt2
|
||||
*
|
||||
* @param dt1 pointer to the first datetime
|
||||
* @param dt1 pointer to the second datetime
|
||||
* @return *dt1 <= *dt2
|
||||
* @param dt1 pointer to the first datetime
|
||||
* @param dt1 pointer to the second datetime
|
||||
* @return *dt1 <= *dt2
|
||||
*/
|
||||
uint8_t udatetime_le(udatetime_t* dt1, udatetime_t* dt2);
|
||||
|
||||
/**
|
||||
* @brief returns *dt1 > *dt2
|
||||
/** @brief returns *dt1 > *dt2
|
||||
*
|
||||
* @param dt1 pointer to the first datetime
|
||||
* @param dt1 pointer to the second datetime
|
||||
* @return *dt1 > *dt2
|
||||
* @param dt1 pointer to the first datetime
|
||||
* @param dt1 pointer to the second datetime
|
||||
* @return *dt1 > *dt2
|
||||
*/
|
||||
uint8_t udatetime_gt(udatetime_t* dt1, udatetime_t* dt2);
|
||||
|
||||
/**
|
||||
* @brief returns *dt1 >= *dt2
|
||||
/** @brief returns *dt1 >= *dt2
|
||||
*
|
||||
* @param dt1 pointer to the first datetime
|
||||
* @param dt1 pointer to the second datetime
|
||||
* @return *dt1 >= *dt2
|
||||
* @param dt1 pointer to the first datetime
|
||||
* @param dt1 pointer to the second datetime
|
||||
* @return *dt1 >= *dt2
|
||||
*/
|
||||
uint8_t udatetime_ge(udatetime_t* dt1, udatetime_t* dt2);
|
||||
|
||||
// rule functions
|
||||
/**************************************************************************/
|
||||
/* zone rule functions */
|
||||
/**************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief unpack rule
|
||||
/** @brief unpack rule
|
||||
*
|
||||
* @param rule_in pointer to packed rule
|
||||
* @param cur_year year: 1 <= y <= 255 (2001 - 2255)
|
||||
* @param rule_out pointer for the output unpacked rule
|
||||
* @return void
|
||||
* @param rule_in pointer to packed rule
|
||||
* @param cur_year year: 1 <= y <= 255 (2001 - 2255)
|
||||
* @param rule_out pointer for the output unpacked rule
|
||||
* @return void
|
||||
*/
|
||||
void unpack_rule(urule_packed_t* rule_in, uint8_t cur_year, urule_t* rule_out);
|
||||
|
||||
/**
|
||||
* @brief sort rule in place
|
||||
/** @brief sort rule in place
|
||||
*
|
||||
* @param rules pointer to rules
|
||||
* @param num_rules the number of rules in the array
|
||||
* @return void
|
||||
* @param rules pointer to rules
|
||||
* @param num_rules the number of rules in the array
|
||||
* @return void
|
||||
*/
|
||||
void sort_rules(urule_t* rules, uint8_t num_rules);
|
||||
|
||||
/**
|
||||
* @brief unpack rules that are active in the current year
|
||||
/** @brief unpack rules that are active in the current year
|
||||
*
|
||||
* @param rules_in pointer to packed rules
|
||||
* @param num_rules the number of rules in the array
|
||||
* @param cur_year year: 1 <= y <= 255 (2001 - 2255)
|
||||
* @param rules_out pointer for the output unpacked rules
|
||||
* @return void
|
||||
* Note this assumes no two rules are active on the same day
|
||||
*
|
||||
* @param rules_in pointer to packed rules
|
||||
* @param num_rules the number of rules in the array
|
||||
* @param cur_year year: 1 <= y <= 255 (2001 - 2255)
|
||||
* @param rules_out pointer for the output unpacked rules
|
||||
* @return void
|
||||
*/
|
||||
// cur_year differs if rule is local time or UTC referenced...
|
||||
// we should be fine since zones using UTC referenced are generally sane
|
||||
void unpack_rules(urule_packed_t* rules_in, uint8_t num_rules, uint8_t cur_year, urule_t* rules_out);
|
||||
|
||||
/**
|
||||
* @brief get the rule that applies at datetime
|
||||
/** @brief get the rule that applies at datetime
|
||||
*
|
||||
* @param rules pointer to rules
|
||||
* @param datetime the datetime to check rules for
|
||||
* @return a pointer the the rule that applies
|
||||
* @param rules pointer to rules
|
||||
* @param datetime the datetime to check rules for
|
||||
* @return a pointer the the rule that applies
|
||||
*/
|
||||
urule_t* get_active_rule(urule_t* rules, udatetime_t* datetime);
|
||||
|
||||
/**
|
||||
* @brief get the offset for zone at datetime, taking into account daylight savings time rules
|
||||
/** @brief get the offset for zone at datetime, taking into account daylight savings time rules
|
||||
*
|
||||
* @param zone pointer to zone
|
||||
* @param datetime the datetime to check rules for
|
||||
* @return the offset for zone at datetime
|
||||
* @param zone pointer to zone
|
||||
* @param datetime the datetime to check rules for
|
||||
* @param offset offset for zone at datetime
|
||||
* @return abbreviation letter
|
||||
*/
|
||||
uoffset_t get_current_offset(uzone_t* zone, udatetime_t* datetime);
|
||||
char get_current_offset(uzone_t* zone, udatetime_t* datetime, uoffset_t* offset);
|
||||
|
||||
/**
|
||||
* @brief unpack timezone
|
||||
/** @brief unpack timezone
|
||||
*
|
||||
* @param name the name of the timezone
|
||||
* @param zone_in pointer to input packed zone
|
||||
* @param zone_in pointer to output unpacked zone
|
||||
* @return void
|
||||
* @param name the name of the timezone
|
||||
* @param zone_in pointer to input packed zone
|
||||
* @param zone_in pointer to output unpacked zone
|
||||
* @return void
|
||||
*/
|
||||
void unpack_zone(uzone_packed_t* zone_in, char* name, uzone_t* zone_out);
|
||||
|
||||
/** @brief advance pointer to list of zone names and returns the prev index into the zone definitions array
|
||||
*
|
||||
* @param list pointer to pointer into zone names list
|
||||
* @return index into the zone definitions array for the zone name before advancement
|
||||
*/
|
||||
uint8_t next_packed_zone(char** list);
|
||||
|
||||
void get_zone_by_name(char* name, uzone_t* zone_out);
|
||||
#endif /* _UTZ_H */
|
||||
|
||||
2
zones.h
2
zones.h
@ -625,7 +625,7 @@ uzone_packed_t zone_defns[165] = {
|
||||
{ 48, 0, 0, { 'W', 'F', 'T','\0','\0'}},
|
||||
};
|
||||
|
||||
char zone_names[1267] = {
|
||||
unsigned char zone_names[1267] = {
|
||||
'A','d','e','l','a','i','d','e','\0', 107, // Adelaide
|
||||
'A','h','m','e','d','a','b','a','d','\0', 84, // Ahmedabad
|
||||
'A','l','m','a','t','y','\0', 56, // Almaty
|
||||
|
||||
Reference in New Issue
Block a user