Fix warnings / compiler errors for SDCC, add Arduino library file

This commit is contained in:
Evey Quirk
2017-01-23 08:56:11 +00:00
parent 4ca5a74cbe
commit 5cb65c8b62
5 changed files with 277 additions and 204 deletions

9
library.properties Normal file
View 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=*

View File

@ -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
View File

@ -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
View File

@ -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 */

View File

@ -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