Timezone identifier support for PHP on Windows

Bug #1451328 reported by Narissa on 2015-05-04
This bug affects 1 person
Affects Status Importance Assigned to Milestone

Bug Description

Last login column for users search is blank (and does not sort in the correct order) also the warning saying 'PHP on your website host does not return a useful value for the timezone identifier (%z) .....' on the admin page is not a fix for the problem and unfortunately some of us are not able to change from hosting on a Windows server.

I am wondering if Mahara is using strftime resulting in the time zone identifier returning 'New Zealand Standard Time' in Windows rather than Linux' +1200 is part of the problem.

I have searched the forums but not found a fix.

Server: Windows 2012 R2
Mahara version: 15.04.0 and 1.9.4
IIS: 8.5 (both servers) also had same problem on a WAMP environment
PHP version: 5.5.3 and 5.5.8
MySQL version: 5.5.40 on both servers

Narissa (narissa-bayler) wrote :
Aaron Wells (u-aaronw) on 2015-05-04
tags: added: windows
tags: added: iis wamp
Changed in mahara:
status: New → Triaged
importance: Undecided → Low
milestone: none → 15.10.0
Aaron Wells (u-aaronw) wrote :

Due to the limited development resources available to the Mahara core team, we don't officially support or test Mahara on platforms other than Ubuntu and Debian. That said, we are always willing to make small code changes to accommodate running on other platforms.

Doing a quick search through the code, I see that, although we have that prominent sanity check for %z, we actually only use %z in one place, during Leap2a exports. So that shouldn't be causing the problem that you're describing. I think the main problem that would cause, is that if you do a Leap2a export & import, you'll get weird dates on, for instance, blog entries.

Looking at the PHP docs for strftime() ( http://php.net/manual/en/function.strftime.php ), I see that %e also doesn't work properly in Windows. We do use that in the "strftimedate" formatting string. However, the string that displays the last login dates on the user search page, is "strftimedatetime" in langconfig.php, which is "%%d %%B %%Y, %%l:%%M %%p". In theory that formatting string should work fine in Windows.

So, I'm not really sure what the fix is here.

Could you take a look in your database and see if the user's dates are stored properly in the "usr.lastlogin" column?

Aaron Wells (u-aaronw) wrote :

Here's another thing you could try to check whether these dates formats are the problems. All the date formats are stored as Mahara language strings, in the langconfig.php file. You could create a local custom override file for this, and change each string one at a time.

Just copy your htdocs/lang/en.utf8/langconfig.php file to htdocs/local/lang/en.utf8/langconfig.php. You'll notice that "strftimew3cdatetime" is the one that has "%z" in it. Try just dropping the %z, or changing it to "+12", and see whether user search works.

Similarly, "strftimedate" is the only one that has "%e" in it. Just change that to "%d" and see if it makes any difference.

Narissa (narissa-bayler) wrote :

Thanks for your help. I nearly added the tag #AaronThisHasYourNameOnIt

The export in Leap2A could be a big problem if we look at suggesting students use another Mahara provider when they leave, such as Nga Manukura o Apopo for nursing graduates as they are most likely using journals

Copying the lanconfig.php file required the removal of some code to stop a fatal error with doubling up on declaring the pluralfunction twice. Didn't make any difference to my lack of last login or blog post dates but the date is being stored correctly in the database. I can do some testing to see if I can work out what's happening with the user display on my dev site.

I exported a site to see what comes out date wise (see below) but I don't have a working one to compare it to. Are you able to confirm if the date below is in the correct format or not?
        <title>Dashboard page</title>


In the meantime I will keep plugging away at the issue. I would really like to solve it as I am keen to use Mahara here.

Narissa (narissa-bayler) wrote :

Feel free to remove my above comment. I've had a chance to look at the issue. For me it appears the best way to go with the %z is to hard code the UTC offset and update it every time daylight savings starts and ends. As you saidthe database is not affected by the format but the Leap2A export is. Just removing the %z from the langconfig.php file won't work because during the export process a colon is added before the penultimate character, so simply removing the %z will leave you with two colons before the seconds, e.g. <published>2015-05-01T16:32::55>.

%e to %d was a quick fix and the reason why the last login date (and other dates) weren't showing is because %l (lower case L) is also not Windows compatible. Interestingly it's not mentioned in the php manual's strftime page but like %e can be replaced with %I (upper case i) giving the same but with leading zero rather than a space.

I guess in the future it would be good if Windows compatible parameters could be used in Mahara and a small formatting fix like the one in Moodle's calendar structure.php page to remove the less than pretty leading zero. (I guess ideally Windows parameters would work/work the same as Linux but I'm thinking I'd have more luck here). :D

Aaron Wells (u-aaronw) wrote :

I see now that at the top of the php.net strftime page, it points you to this URL to see the date formatting parameters that are supported in Windows:


Hm, so it appears that the following PHP strftime() parameters are not supported in Windows: CDFGPRTVeghklnrtu. And also "z" and "Z" give the name of the timezone instead of the timezone offset (i.e. -0500). In searching for these in our code base, I found that the only ones we use are %e, %l, %k, and %z.

Now for %e, %l, and %k, in Windows you can use the "#" prefix which tells it to strip leading zeroes. So the equivalents are %e => %#d; %l (lowercase L) => %#I (uppercase I); %k => %#H. *However*, the "#" doesn't work in Linux. So you have to use a different language string for each platform.

One way to handle this is with local language string overrides. However, I also noticed that Mahara already contains code to do the Windows workarounds, but it's incomplete. All the date formats that are stored in language strings, are normally called using the Mahara function format_date() in htdocs/lib/mahara.php. This method actually already contains code to detect Windows and swap "%e" for "%#d". So you could try adding additional code there to make the other substitutions as well.

(I noticed that ADODB and Dwoo also include code that does this same substitution, but I don't think it's meant to be part of their external API, so it's probably better not to swap out for that.)

Aaron Wells (u-aaronw) wrote :

For anyone who's interested, here's a table I found, of all the format strings that aren't supported in Windows, and what to substitute for them. Fortunately in Mahara all we use is %z, %e, %k, and %l.

%C -> 2-digit represation of the century (19 for 1959)
%V -> Week number of the given year starting with the first week with at least 4 weekdays
%g -> Two-digit year of the current %V week
%G -> Four-digit year of the current %V week
%u => Day of week with Monday = 1 -> Sunday = 7. Can calculate from %w (Sunday = 0 -> Saturday = 6)
%z => Timezone offset, i.e. -0500 for US Eastern Standard Time.
%Z => Timezone abbreviation, i.e. EST for US Eastern Standard Time.
%s => time()
%P -> strtoupper(%p)
%n => \n (newline)
%t => \t (tab)
%D -> %m/%d/%y
%F -> %Y-%m-%d
%R -> %H:%M
%T -> %H:%M:%S
%r => %I:%M:%S:%P
%h -> %b
%e -> %#d // Used in Mahara
%k => %#H // Used in Mahara
%l => %#I // Used in Mahara

Aaron Wells (u-aaronw) on 2015-10-23
Changed in mahara:
milestone: 15.10.0 → 16.04.0
Aaron Wells (u-aaronw) on 2016-04-28
Changed in mahara:
milestone: 16.04.0 → none
Aaron Wells (u-aaronw) wrote :

If anyone who is really committed to running Mahara on a non-standard platform would like to fix this, I think the only really robust solution would be to switch from strftime() to date() or DateFormat, both of which use a different formatting standard that apparently is *not* OS-dependent. The main downside to that, is that it would make all of the datetime formats in our language files obsolete, because the format is completely different. So all the translated langpacks would need to be updated or they would stop working. (Potentially that update could be automated.)

There's also the simpler possibility of removing all the incompatible format strings from our core lang files. But I wouldn't want to upstream that because it would leave us printing leading zeroes in front of all of our hours and days of the month, e.g. "July 04, 07:30pm". (We could write more code to strip out those leading zeroes, but that would be hacky and brittle.)

Aaron Wells (u-aaronw) wrote :

We've also had a report of this coming from an Amazon cloud server running a lightweight Linux distro that uses "musl" for its C standard library instead of glibc: https://en.wikipedia.org/wiki/Musl

Apparently glibc includes several formatting options (such as %l) that are not part of the POSIX standard: http://pubs.opengroup.org/onlinepubs/007908799/xsh/strftime.html

Aaron Wells (u-aaronw) wrote :
To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers

Bug attachments