UTC Time Conversion
Chris Hall (132) 3499 posts |
I have a need to convert a 5byte UTC time to a UTC time string. The only functions I have found (OS_ConvertStandardDateAndTime for example) convert to local time zone including DST. So at the moment I use local time for an embedded <time> tag in a GPX file. Is there a function to convert UTC 5byte time value to a standard (or specified) time/date string also in UTC – here I use OS_ConvertDateAndTime to obtain <time>2017-08-24T15:49:20.76Z</time> but that is a local time and thus not strictly correct (at least during the summer)? I have found how to set the RISC OS clock to a UTC 5byte time derived from the GPS signal: SYS “Territory_SetTime”,tmm% and this seems to work on RISC OS 4/6 and RISC OS 5. I have written my own routine to convert the UTC ordinals of the time and date (from an NMEA sentence received from the GPS module) to a 5 byte UTC value but is there a built-in routine?
|
Jeffrey Lee (213) 6046 posts |
I’m not sure if there’s a way of doing a direct conversion to string, but Territory_ConvertTimeToUTCOrdinals looks like it should get you most of the way there.
It’s not documented on the wiki yet, but TerritoryManager 0.47+ has a Territory_ConvertTimeFormats SWI which is able to do arbitrary conversions between 5-byte times, ordinals, and local/UTC times. So calling with R3=&302 should be what you need. |
Chris Hall (132) 3499 posts |
Many thanks for that. I need the routines to work on RISC OS 4.02, 4.39, 5.16, 5.2x and 6 so I think I may be stuck with what I have? |
Steve Drain (222) 1620 posts |
The method I used in Basalt to get UTC information 1 when a SWI returned in local time was to subtract the time zone interval (Territory_ReadCurrentTimeZone) from the 5-byte value before calling the SWI. That is a bit vague, but I could look up some code if it would help. 1 eg: |
Martin Avison (27) 1417 posts |
Note that this is not correct for all years (from 1752) because a year is about 365.242 days. |
Rick Murray (539) 13385 posts |
Steve – do you have a few lines of code to demonstrate doing that with a five byte value? Wouldn’t it require an unaligned access, or have I got my byte ordering back to front? |
Jeffrey Lee (213) 6046 posts |
It looks like Territory_ConvertTimeFormats was first available in RISC OS 5.20. For older OS versions I guess you’ll have to use an implementation of your own (be careful with leap years and leap seconds if you want it to be accurate), or apply the time zone offset manually as Steve suggests. Maybe there’d be some issues here with daylight saving time, I’m not sure exactly where it gets applied in all the different OS versions. |
Steve Drain (222) 1620 posts |
Rick, here it is, straight out of the code. I wrote this well over a decade ago and I doubt it has been tested by any user, so be kind. ;-) The UTC block is stored in the BASIC workspace at the AR_UTCT offset from ARGP.
|
Steve Drain (222) 1620 posts | |
Chris Hall (132) 3499 posts |
Note that this is not correct for all years (from 1752) I am only trying to cover dates from 2016 to 04:28:56 on 18-Mar-2074 and am prepared to overlook leap seconds. Dates after 2074 are excluded for two reasons: one is that the GPS module can return a date of 2080 if its battery becomes discharged, is being used for the first time or has suffered some sort of error not mentioned in the documentation. Note as the NMEA sentences do not include century data it is possible that it thinks it is returning 1980 as a date. Once it has a fix it will return date and time from the satellite’s atomic clock but until then it returns NMEA sentences containing date and time from its internal RTC with position information marked as invalid. The GPS module keeps time using a small watch battery whilst it is switched off. The other reason is that it makes BASIC arithmetic easier when using the top 4 bytes of the UTC time as it is always less than &7FFFFFFF. |