RISC OS Open
Safeguarding the past, present and future of RISC OS for everyone
ROOL
Home | News | Downloads | Bugs | Bounties | Forum | Documents | Photos | Contact us
Account

Previous|Next

  • Tickets
  • » Ticket #391

Ticket #391 (Fixed)Thu Jul 17 21:53:26 UTC 2014

localtime() ignores manual timezone configuration

Reported by: Rick Murray (539) Severity: Normal
Part: RISC OS: Software library Release:
Milestone: Status Fixed

Details by Rick Murray (539):

The localtime() function determines the time zone offset by a bizarre method of reading the DST flag and then calling Territory_ReadTimeZones. Unfortunately, in territories with multiple timezones (such as the USA), this returns the first timezone defined. If you are using a different one (say, PST instead of EST), there is no way that your machine will ever return the correct local time.

Fix? I presume the complicated code is to support the enhancements to the setlocale() function where you can specify custom time zones on a per-application basis. Fair enough.

However when the standard default locale is in use, just call Territory_ReadCurrentTimeZone and be done with it.

More info here: https://www.riscosopen.org/forum/forums/4/topic…

Changelog:

Modified by Rick Murray (539) Sun, July 20 2014 - 14:33:22 GMT

  • Attachment added: time.txt

Fix is as follows:

<pre>struct tm *localtime(const time_t *timer)
{
time_t t;
static struct tm _tms;
int dst;
int territory;
int v;
_kernel_swi_regs r;

t = *timer; if (t == (time_t)-1) { memset(&tms, 0, sizeof(tms)); tms.tmmday = 1; /* 1st day of 1900 */ return &_tms; } // Read DST flag (it is needed for time_to_tm at the end in any case) dst = -1; v = _kernel_osbyte(161, 220 /* AlarmAndTimeCMOS */, 0); // read CMOS if (v >= 0) dst = v & 0×8000; // DST flag is bit 7 // What locale are we using? territory = __locales[N_LC_TIME]; if ( !territory ) { // If C locale, use the currently configured timezone // of the currently configured territory. r.r2 = 0; // make sure it does not say “ZONE” kernel_swi(TerritoryReadCurrentTimeZone, &r, &r); t += (r.r1 / 100); // centiseconds -> seconds } else { // Custom locale – work it out from the specified timezone and DST setting // read timezone information from Territory r.r0 = TERRITORY_EXTRACT(territory); r.r1 = TERRITORY_TZ_EXTRACT(territory); r.r4 = TERRITORY_TZ_API_EXT; /* If not supported, never mind */ if (kernel_swi(TerritoryReadTimeZones, &r, &r) == NULL) { v = (dst == 0×8000) ? r.r3 : r.r2; t += v / 100; /* centiseconds -> seconds */ } } /* Already corrected for locale, so just need to mangle it */ /* into a suitable structure */ return time_to_tm(&_tms, t, dst);

}</pre>

Tested with UK: GMT, BST, CET, CEST (my version of UK that includes CET/CEST).
Tested with USA: EST, EDT, PST, AKST.
In all cases, the time returned by asctime(localtime(&meh)) matches *Time.

In case the bug tracker mangles the code, I have attached the “time” source.

Modified by Sprow (202) Sat, August 02 2014 - 08:39:44 GMT

  • Summary changed from localtime() is broken to localtime() ignores manual timezone configuration
  • Part changed from Unspecified to RISC OS: Software library

Awaits regression testing per
https://www.riscosopen.org/forum/forums/4/topic…

Suggest old and new C library on 3.10 3.50 3.60 3.70 4.0x with whatever the ROM vintage territory manager and UK territory is. Can stop at 4.0x since 5.0x is basically a 32 bit version of same.

Modified by Rick Murray (539) Mon, February 16 2015 - 20:46:05 GMT

Followed up here: https://www.riscosopen.org/forum/forums/4/topic…

RISC OS 3.10 (Archie emulator) and RISC OS 3.5 (RedSquirrel) both appear to exhibit a small time disparity of 7 minutes and 13 seconds. No obvious cause for this has been identified, and RISC OS 3.7 on the same RedSquirrel does NOT misbehave. Neither does RISC OS 5.

My suggestion would be a #ifdef to provide the existing code to older clients using the PlingBoot version of CLib (as the problem was never noticed on them before due to the lack of softloaded territory modules, etc etc) while providing the corrected code to RISC OS 5 (so “going forward” it can work correctly).

Modified by Sprow (202) Thu, February 19 2015 - 23:06:34 GMT

Little puzzled at what’s being compared in the posted results, why compare a 32 bit neutral CLib with your changed one?
We want to compare the
ROM C library + ROM territory + ROM territory module
with a test application (compiled for APCS-R) against
Updated C library + ROM territory + ROM territory module
to see if the case of the default C locale isn’t affected by the update. I wouldn’t expect the result of the non default locale to be right prior to RISC OS 5 since the territory SWIs didn’t return anything useful for anything but the base territory they represent, so as long as it doesn’t data abort or anything silly it’d be OK to get a junk result there.

Rinse & repeat for each OS version.

There’s no need for #ifdef’s as there aren’t any new SWIs implicated here.

Modified by Rick Murray (539) Wed, March 18 2015 - 20:31:40 GMT

Comparing a 32 bit neutral CLib as that is what people will be using on the systems affected. You could probably count people using ROM CLib on the fingers of one hand…

“to see if the case of the default C locale isn’t affected by the update” – how do you mean exactly? I was looking at the result of calling gmtime() and localtime(). Is there something else I ought to be testing?

The #ifdef suggestion was because the same updated CLib appears to give different results for localtime() on RISC OS 3.5 and RISC OS 3.7 (the 433 seconds quirk). As you point out, changing territory and timezone was a bit of a non-starter on older systems, so having an #ifdef for building 32 bit (RISC OS 5) versions of the library would mean that the issue is corrected for new machines, and older ones receive the same (broken) code as before, which was not noticed in, oh, twenty-odd years. ;-)

Modified by Sprow (202) Thu, March 19 2015 - 09:19:21 GMT

“Comparing a 32 bit neutral CLib as that is what people will be using on the systems affected”, my point being that you said you tested the existing neutral C lib (which this ticket proposes is where there is a bug) with your fixed neutral C lib, which is 2 tests yielding only 1 result. Test ROM C lib and with fixed neutral C lib is 2 tests yielding 2 results.

“to see if the case of the default C locale isn’t affected by the update”, a simple round trip convert and convert back with gmtime() localtime() sounds fine.

Modified by Rick Murray (539) Sat, May 07 2016 - 13:13:14 GMT

Test results here: https://www.riscosopen.org/forum/forums/4/topic…

Modified by Jeffrey Lee (213) Sun, May 22 2016 - 12:46:57 GMT

  • Status changed from Open to Fixed

These fixes should now be available in CLib 5.90

https://www.riscosopen.org/viewer/revisions/log…

Modified by Rick Murray (539) Fri, June 10 2016 - 17:45:06 GMT

Tested with recent RISC OS build and a standalone UK territory that has CET and CEST timezones added.

Fix confirmed.

  • Comment on, or change status of, this ticket

Previous|Next

Search tickets

Social

Follow us on and

ROOL Store

Buy RISC OS Open merchandise here, including SD cards for Raspberry Pi and more.

Donate! Why?

Help ROOL make things happen – please consider donating!

RISC OS IPR

RISC OS is an Open Source operating system owned by RISC OS Developments Ltd and licensed primarily under the Apache 2.0 license.

Options

  • Tickets
  • New ticket
  • Milestones
  • Subversion: Changesets
  • Subversion: Browse
  • CVS: Revisions
  • CVS: Browse
  • Search

RSS feeds Rss

  • Tickets
  • Everything!
  • More feeds...
Site design © RISC OS Open Limited 2018 except where indicated
The RISC OS Open Collaboa theme is distantly based on the Collaboa default layout

Valid XHTML 1.0  |  Valid CSS

Powered by Collaboa
This site runs on Rails

Hosted by Arachsys