garmin: add a _third_ time offset field
So FIT files seem to have many many different ways to describe time offsets. And I'm not talking about the overall Garmin time offset of 631065600, which is the conversion from the "Unix Epoch" (Jan 1, 1970) to the "Garmin Epoch" (Dec 31, 1989). No, I'm talking just about "device time" to "local time" to "UTC" conversions. The DEVICE_SETTINGS message has two different fields for time offsets: there's a "UTC offset" (presumably this is the timezone the device is set to), and a "time offset" which we actually use to transform the recorded time of the dive into the local time that we report. But the Suunto FIT export doesn't seem to use either of those, and instead Nick Clark points outthe Suunto FAQ: "Timestamp fields are deliberately defined as UTC time so that they may be conveniently displayed in the local time if so desired. In some instances it is useful to know the UTC offset when the file was generated (possibly different from when it is decoded). This can be accomplished by logging a single message containing both a local_timestamp and a timestamp field. This will establish the UTC offset of the file. Presently these fields are predefined for activity and monitoring messages" so to get the actual local time, instead of getting it from the DEVICE_SETTINGS message, we now have to parse the ACTIVITY message, and take the difference between the regular timestamp and the "local_timestamp" field. The great thing about standards is that there are so many to choose from. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
dc8f32609e
commit
e81eca685a
@ -65,6 +65,7 @@ struct garmin_sensor {
|
||||
struct record_data {
|
||||
unsigned int pending;
|
||||
unsigned int time;
|
||||
unsigned int timestamp;
|
||||
|
||||
// RECORD_DECO
|
||||
int stop_time;
|
||||
@ -492,6 +493,7 @@ struct field_desc {
|
||||
// Convert to "standard epoch time" by adding 631065600.
|
||||
DECLARE_FIELD(ANY, timestamp, UINT32)
|
||||
{
|
||||
garmin->record_data.timestamp = data;
|
||||
if (garmin->callback) {
|
||||
dc_sample_value_t sample = {0};
|
||||
|
||||
@ -652,7 +654,11 @@ DECLARE_FIELD(ACTIVITY, num_sessions, UINT16) { }
|
||||
DECLARE_FIELD(ACTIVITY, type, ENUM) { }
|
||||
DECLARE_FIELD(ACTIVITY, event, ENUM) { }
|
||||
DECLARE_FIELD(ACTIVITY, event_type, ENUM) { }
|
||||
DECLARE_FIELD(ACTIVITY, local_timestamp, UINT32) { }
|
||||
DECLARE_FIELD(ACTIVITY, local_timestamp, UINT32)
|
||||
{
|
||||
int time_offset = data - garmin->record_data.timestamp;
|
||||
garmin->dive.time_offset = time_offset;
|
||||
}
|
||||
DECLARE_FIELD(ACTIVITY, event_group, UINT8) { }
|
||||
|
||||
// SPORT
|
||||
@ -1693,10 +1699,22 @@ garmin_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||
{
|
||||
garmin_parser_t *garmin = (garmin_parser_t *) abstract;
|
||||
dc_ticks_t time = 631065600 + (dc_ticks_t) garmin->dive.time;
|
||||
int timezone = DC_TIMEZONE_NONE;
|
||||
|
||||
// Show local time (time_offset)
|
||||
dc_datetime_gmtime(datetime, time + garmin->dive.time_offset);
|
||||
datetime->timezone = DC_TIMEZONE_NONE;
|
||||
|
||||
/* See if we might have a valid timezone offset */
|
||||
if (garmin->dive.time_offset || garmin->dive.utc_offset) {
|
||||
int offset = garmin->dive.time_offset - garmin->dive.utc_offset;
|
||||
|
||||
/* 15-minute (900-second) offsets are real */
|
||||
if ((offset % 900) == 0 &&
|
||||
offset >= -12*60*60 &&
|
||||
offset <= 14*60*60)
|
||||
timezone = offset;
|
||||
}
|
||||
datetime->timezone = timezone;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user