Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatic DST support #3072

Merged
merged 12 commits into from
May 20, 2018
Next Next commit
Automatic DST support
  • Loading branch information
nmaggioni committed Apr 19, 2018
commit eae76b93ccd66948337c84fc1350935b2690c50c
26 changes: 20 additions & 6 deletions src/main/common/time.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "drivers/time.h"

#define UNIX_REFERENCE_YEAR 1970
#define UNIX_REFERENCE_DOW 3
#define MILLIS_PER_SECOND 1000

// rtcTime_t when the system was started.
Expand All @@ -51,6 +52,7 @@ PG_REGISTER_WITH_RESET_TEMPLATE(timeConfig_t, timeConfig, PG_TIME_CONFIG, 0);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're adding fields to the parameter group. Please also increase version number in the declaration PG_REGISTER_WITH_RESET_TEMPLATE

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rookie mistake, my bad.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No worries, I keep forgetting to do this myself 😉

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any more work left to be done on this? Sorry to be bothering, it seems that I cannot manually mark this request as solved.

PG_RESET_TEMPLATE(timeConfig_t, timeConfig,
.tz_offset = 0,
.tz_automatic_dst = false,
);

static rtcTime_t dateTimeToRtcTime(dateTime_t *dt)
Expand Down Expand Up @@ -120,14 +122,26 @@ static bool rtcIsDateTimeValid(dateTime_t *dateTime)
(dateTime->millis <= 999);
}

static void dateTimeWithOffset(dateTime_t *dateTimeOffset, dateTime_t *dateTimeInitial, int16_t minutes)
static bool isDST(rtcTime_t t) {
dateTime_t dateTime;
rtcTimeToDateTime(&dateTime, t);
if (dateTime.month < 3 || dateTime.month > 11) { return false; }
if (dateTime.month > 3 && dateTime.month < 11) { return true; }
uint8_t dow = (uint8_t) (((t / MILLIS_PER_SECOND) / 86400) + UNIX_REFERENCE_DOW) % 7;
int previousSunday = dateTime.day - dow;
if (dateTime.month == 3) { return previousSunday >= 8; }
return previousSunday <= 0;
}

static void dateTimeWithOffset(dateTime_t *dateTimeOffset, dateTime_t *dateTimeInitial, int16_t minutes, bool automatic_dst)
{
rtcTime_t initialTime = dateTimeToRtcTime(dateTimeInitial);
rtcTime_t offsetTime = rtcTimeMake(rtcTimeGetSeconds(&initialTime) + minutes * 60, rtcTimeGetMillis(&initialTime));
if (automatic_dst && isDST(offsetTime)) { offsetTime += 3600; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, align the #if at the start of the line. Don't put the code inside the if in the same line. We use:

if (condition) {
    do_foo();
}

(this applies to more places in the diff, but no reason to repeat the same comment in all of them)

rtcTimeToDateTime(dateTimeOffset, offsetTime);
}

static bool dateTimeFormat(char *buf, dateTime_t *dateTime, int16_t offset)
static bool dateTimeFormat(char *buf, dateTime_t *dateTime, int16_t offset, bool automatic_dst)
{
dateTime_t local;

Expand All @@ -139,7 +153,7 @@ static bool dateTimeFormat(char *buf, dateTime_t *dateTime, int16_t offset)
if (offset != 0) {
tz_hours = offset / 60;
tz_minutes = ABS(offset % 60);
dateTimeWithOffset(&local, dateTime, offset);
dateTimeWithOffset(&local, dateTime, offset, automatic_dst);
dateTime = &local;
}

Expand Down Expand Up @@ -176,17 +190,17 @@ uint16_t rtcTimeGetMillis(rtcTime_t *t)

bool dateTimeFormatUTC(char *buf, dateTime_t *dt)
{
return dateTimeFormat(buf, dt, 0);
return dateTimeFormat(buf, dt, 0, false);
}

bool dateTimeFormatLocal(char *buf, dateTime_t *dt)
{
return dateTimeFormat(buf, dt, timeConfig()->tz_offset);
return dateTimeFormat(buf, dt, timeConfig()->tz_offset, timeConfig()->tz_automatic_dst);
}

void dateTimeUTCToLocal(dateTime_t *utcDateTime, dateTime_t *localDateTime)
{
dateTimeWithOffset(localDateTime, utcDateTime, timeConfig()->tz_offset);
dateTimeWithOffset(localDateTime, utcDateTime, timeConfig()->tz_offset, timeConfig()->tz_automatic_dst);
}

bool dateTimeSplitFormatted(char *formatted, char **date, char **time)
Expand Down
1 change: 1 addition & 0 deletions src/main/common/time.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ static inline timeDelta_t cmpTimeUs(timeUs_t a, timeUs_t b) { return (timeDelta_

typedef struct timeConfig_s {
int16_t tz_offset; // Offset from UTC in minutes, might be positive or negative
bool tz_automatic_dst; // Automatically handle DST or ignore it
} timeConfig_t;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than 2 variables, use just one uint8_t named tz_automatic_dst which can take the values OFF (default), US,EU, etc... That way we use a single byte for storage and users just need to change one setting to make it work. Put a comment at the right indicating that the value comes from tz_automatic_dst_e.


PG_DECLARE(timeConfig_t, timeConfig);
Expand Down
2 changes: 2 additions & 0 deletions src/main/fc/settings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1647,6 +1647,8 @@ groups:
- name: tz_offset
min: -1440
max: 1440
- name: tz_automatic_dst
type: bool

- name: PG_DISPLAY_CONFIG
type: displayConfig_t
Expand Down