How to convert the number of seconds from an epoch into UTC using the datetime function.

166 visualizzazioni (ultimi 30 giorni)
I am struggling to convert the number of seconds from an epoch (1980-01-06 GPS epoch) into UTC using the datetime function. The following commands give me a time of 18-Mar-2021 20:37:31, however in UTC this should be 18-Mar-2021 20:37:13 since I would need to subtract out the number of leap seconds from the total (currently there are 18 leap seconds since the 1980-01-06 GPS epoch).
NoOfSeconds=1300135051;
datetime(NoOfSeconds,'convertfrom','epochtime','Epoch','1980-01-06')
Can the datetime function automatically account for leapseconds in this conversion? I tried using the 'TimeZone','UTCLeapSeconds' name/value pair, but this adds 18 seconds since it assumes the time is already in UTC.

Risposta accettata

Peter Perkins
Peter Perkins il 2 Ago 2021
Matthew, this is easier than you think. In MATLAB, 'TimeZone','UTC' is sort of a ficticious timeline that pretends that leaps seconds don't exist (because hardly anyone wants to actually account for leap seconds). 'UTCLeapSeconds' is the timeline that knows all about leap seconds. The GPS timeline (in the real world) ticks off the same leap seconds as 'UTCLeapSeconds' in MATLAB does, it just doesn't treat them specially. So for the purposes of arithmetic, i.e. elapsed time, 'UTCLeapSeconds' is what you want. Then all you have to do is change to 'UTC' (or not, it's up to you).
>> epoch = datetime(1980,1,6,'TimeZone','UTCLeapSeconds')
epoch =
datetime
1980-01-06T00:00:00.000Z
>> dtUTC = epoch + seconds(1300135051)
dtUTC =
datetime
2021-03-18T20:37:13.000Z
>> dtUTC.TimeZone = 'UTC'
dtUTC =
datetime
18-Mar-2021 20:37:13
Also, this Answer might be helpful:
If I may ask, I would be interested in hearing more about how you work with GPS timestamps. Do you always get "seconds since 1980" as your input? Do you need to work with "week number, seconds within week"? Do you need to work with "human readable timestamps" (e.g. 18-Mar-2021 20:37:31) that refer to the GPS timeline (as opposed to UTC)? Do you need to convert back to one of those GPS time formats? Thanks in advance for anything you are able to share.
  7 Commenti
James Tursa
James Tursa il 23 Nov 2024 alle 1:00
Modificato: James Tursa il 23 Nov 2024 alle 1:10
One needs to be careful with this approach, since a direct conversion of UTCLeapSeconds into UTC during a leap second creates a jump at a location that doesn't match posixtime. E.g.,
format longg
% Create a GPS seconds in the middle of a leap second.
GPS_epoch = datetime(1980,1,6,'TimeZone','UTCLeapSeconds')
GPS_epoch = datetime
1980-01-06T00:00:00.000Z
dtleap = datetime(2016,12,31,23,59,60.5,'TimeZone','UTCLeapSeconds')
dtleap = datetime
2016-12-31T23:59:60.500Z
gps = seconds(dtleap - GPS_epoch)
gps =
1167264017.5
% Now reconstruct the datetime associated with this GPS time
dtutc1 = GPS_epoch + seconds(gps)
dtutc1 = datetime
2016-12-31T23:59:60.500Z
% Direct conversion to UTC
dtutc1.TimeZone = 'UTC';
dtutc1.Format = 'dd-MMM-uuuu HH:mm:ss.S z'
dtutc1 = datetime
31-Dec-2016 23:59:59.5 UTC
Well, it jumped backwards instead of counting into the next day. This conflicts with the posixtime result:
dtgps2 = GPS_epoch + seconds(gps)
dtgps2 = datetime
2016-12-31T23:59:60.500Z
dtutc2 = datetime(1970,1,1,'TimeZone','UTC') + seconds(posixtime(dtgps2));
dtutc2.Format = 'dd-MMM-uuuu HH:mm:ss.S z'
dtutc2 = datetime
01-Jan-2017 00:00:00.5 UTC
Here we get the leap second itself counting into the next day. Bottom line is to use posixtime on the UTCLeapSeconds version of the datetime BEFORE converting to UTC if you want this consistency.
Side Note: MATLAB may be changing the behavior of the direct UTCLeapSeconds to UTC conversion in a future release to be consistent with posixtime, so the direct conversion of UTCLeapSeconds to UTC may not behave the same as the above in future MATLAB releases.
Peter Perkins
Peter Perkins circa 6 ore fa
James, you are mixing apples and oranges. "UTCLeapSeconds" represents the real-world timeline that official UTC clocks follow, including counting leap seconds. "UTC" is a ficticious timeline that makes life less painful for the overwhelming majority of people who do not want to complicate their life with leap seconds.
2016-12-31T23:59:60.500Z does not exist on the ficticious "UTC" timeline. If I want to convert that to "UTC", should it map to 23:59:59.5 on that timeline, or to 00:00:0.5 on the next day? I would argue that the former creates fewer problems because it does not change the date, and I guess you would argue that since POSIX defines the POSIX time during a leap second as the 0th second of the next day, that's how the conversion should work. But the real answer is that there is no answer. It can't possibly be a lossless conversion.
This
dtutc2 = datetime(1970,1,1,'TimeZone','UTC') + seconds(posixtime(dtgps2))
adds an elapsed time that was calculated under "UTCLeapSeconds" to a "UTC" datetime. They should not be mixed, and it's going to lead to inconsistencies.
It seems like maybe the underlying issue is that UTCLeapSeconds only supports the ISO display format, and you'd like more flexibility, so you are partially using "UTC", and partially "UTCLeapSeconds".

Accedi per commentare.

Più risposte (2)

Matthew Casiano
Matthew Casiano il 31 Lug 2021
Since there is a leapseconds table included in Matlab, there is a workaround to obtain the cumalative number of leap seconds. This can then be subtracted off of the total number of seconds from an epoch.
% Determine the number of leap seconds since the 06-Jan-1980 GPS epoch by using a Matlab-defined timetable array called 'leapseconds'.
TimeTableLeapSeconds=leapseconds; % Matlab-defined timetable array of leap seconds information
CurrentDateTime=char(datetime('now')); % converts the current time to a character array
DateTimeRange = timerange('06-Jan-1980 00:00:00',CurrentDateTime); % creates a timerange object with the desired time range
[tf, whichrows]=containsrange(TimeTableLeapSeconds,DateTimeRange); % determines which rows of the leap seconds timetable are within the time range
AllRowsRange=TimeTableLeapSeconds(whichrows,1); % selects the first column of all rows in the range which is a timetable containing the leap second sign
AllLeapSecondSignsRange=char(AllRowsRange.Type); % convert timetable array to character array containing all the leap second signs within the time range
AllLeapSecondsRange=str2double(AllLeapSecondSignsRange+"1"); % append '1' to the sign and create a numeric array with all the leap seconds within the time range
CumLeapSecondAdj=sum(AllLeapSecondsRange); % sum contents of the numeric array producting the cumulative leap second adjustment

Sarthak
Sarthak il 13 Mar 2024
function date = gps2utc(g0, g1)
date = datevec(datetime(g0*604800+g1,'convertfrom','epochtime','Epoch','1980-01-06'));

Categorie

Scopri di più su Dates and Time in Help Center e File Exchange

Tag

Prodotti


Release

R2020b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by