Changing Date Format to 'DD-MMM-YY'
#1
I was trying to customise my regional date format for 'English (Australia)' to show 'dd-mmm-yy' (eg: 01-Dec-22).

This format was not listed as an available option so I discovered '/storage/.kodi/addons/resource.language.en_au/resources/langinfo.xml' and decided to modify that.

I cloned and renamed one of the existing '<region>' entries and modified its '<dateshort>' to be 'DD-MMM-YY' as per what appeared to be the pattern in use.  Unfortunately, that produced '1-December-22' instead of the expected '01-Dec-22'.

Seeing that ‘mm’ was used for minutes within other areas of the format string, I initially dismissed lower case as a possible solution and continued my research to no avail.  However, in one final desperate attempt before giving up and moving on, ‘decided to try 'DD-mmm-YY' (lower-case 'mmm') and it produced the required result.

I hope that someone else finds this useful one day.

As an aside:  This is not a common Australian date format, however, I find 'DD-MMM-YY' to be an acceptable compromise between brevity and unambiguity (spelled month).  Even on systems providing regional preferences, one can never be completely sure if a date format has been hard-coded to the cultural norm of the programmer or programming tool, normally 'mm/dd/yy[yy]'.  NOT seeing a date as 'DD-MMM-YY' prompts me to scrutinise the date more closely.
Reply
#2
I may have uncovered an undocumented feature in the KODI/Python API.

I have set my short and long date formats to 'DD-mmm-YY' and 'ddd, D MMMM YYYY' respectively in 'langinfo.xml'.  These settings produce the desired results on the KODI GUI.

When I use 'xbmc.getRegion('dateshort')' or 'xbmc.getRegion('datelong')' inside an add-on, I get an almost correct Python 'strftime()' formatting string, but not exactly.

For 'dateshort', 'DD-mmm-YY' yields '%d-mmm-YY' instead of ' %d-%b-%y'.
For 'datelong', 'ddd, D MMMM YYYY' yields 'ddd, %d %B %Y' instead of ' %a, %d %B %Y'.

When I compare my custom formats to some of the standard formats provided, those all seem to yield valid Python 'strftime()' formatting strings.  I suspect that I have stumbled upon an edge case whereby an unanticipated format for the GUI was not recognised and converted by getRegion().

I did think that I would have to parse/validate the returned getRegion() string prior to use with strftime(), the above results have confirmed my suspicions.

As far as I can tell, the documentation only claims to return a 'Region setting' without elaborating on the precise formatting this entails.  Perhaps resemblance to a strftime() formatting string is coincidental.
Reply
#3
1) I dug into the source code to try to discover if 'mmm' worked by design, of was it a lucky accident.  As it turned out, it was a bit of both.

In 'xbmc-master/xbmc/XBDateTime.cpp' I found the function 'GetAsLocalizedDate'.

This function reads through the provided format string and does a case-blind count of each type of formatting character.  Using 'M' or 'm' for month as an example, if the count is 1, it will provide a non-zero-padded month number.  If the count is 2, it will provide a 2 digit month number, zero-padding where necessary.

Any other character count falls into the 'else' clause where the localised month name string is looked-up using the month number.  There is a ternary operator based on a lower case 'm' determining whether to add 20 or 50 to the month number to get the appropriate localised month name from 'strings.po'.

Any number of lower case 'm's greater than 2 will produce the abbreviated month name (I tried with 8!).  Any number of upper case 'M's greater than 2 will produce the complete month name.  Formatting the day works in the same way except for the formatting character.

Lower case 'm' functionality is by design, but undocumented outside of the code as far as I can tell.  I am currently working on updated text for the 'langinfo.xml' section of the 'Language support' Wiki page in case this information is of use to others.  I will update the Wiki as soon as I can create an account.

2) Whilst I was looking into the source code, I also delved into the Python getRegion() function and I believe that I have discovered the cause of the issue that I identified previously with malformed Python format strings.

The 'GetAsLocalizedDate' function inspects the formatting string character by character and produces the required formatted output whereas the 'getRegion' function does a text search-and-replace operation on a number of commonly expected formatting sequences.  If an uncommon, yet valid, sequence is present, it is overlooked.

As there is no single source of truth, the current arrangement produces different results.

The 'GetAsLocalizedDate' function would interpret 'MMMMMM' as a full month name whereas the 'getRegion' function would probably mangle it into something like '%BMM'.

2a) I'd like to propose that an addition Boolean parameter be added to the 'GetAsLocalizedDate' function that determines the type of string that will be returned.  'False' will return a normally formatted date string whilst 'True' will return the Python formatting string.

The 'GetAsLocalizedDate' function will always build the formatted date string and the formatting string in parallel but at the end, determine which string is to return based on the value of the new Boolean flag.

Function overloading can be used to maintain backwards compatibility simply calling the updated function with a hard-coded 'False' for the new parameter. The 'getRegion' function, on the other hand, will call the updated 'GetAsLocalizedDate' function directly on a dummy date object with 'True' for the new parameter.

2b) As an alternative to the proposal above, 2 new 'getLocalShortDate' and 'getLocalLongDate' functions could be added to the Python API.  These functions would take a Python date object as an input argument and return an appropriately formatted string effectively calling the 'GetAsLocalizedDate' function internally.

2c) Perhaps a series of 'getSetting' functions could be added to the 'xbmc' module to get the raw setting string from the XML file so that the Python programmer can do with it as they wish.

2d) Duplicate the 'GetAsLocalizedDate' logic in 'getSetting', however, we are back to 2 sources of truth if not maintained correctly.

2e) Finally, perhaps a more comprehensive suite of replacement strings could be added to the 'getRegion' function.  Again, there would still be 2 sources of truth for date formatting.

Note: There appears to be 2 versions of the 'getRegion' function, however, for the purposes of this discussion, I have treated them as one.

xbmc-master/xbmc/addons/interfaces/General.cpp -> Interface_General::get_region
and
xbmc-master/xbmc/interfaces/legacy/ModuleXbmc.cpp -> getRegion

I intend to create a virtual machine running Ubuntu so that I can put together a Kodi build environment enabling me to experiment with some of these ideas.  I'm a semi-competent C programmer given enough access to Google and StackOverflow, but I have only ever tinkered with C++ so I apologies if I confused some of the nomenclature (eg. function vs method).  I know what GitHub is, but I have never used it to contribute to a project.  Fun times ahead!
Reply
#4
I have managed to download and build Kodi 21.0-ALPHA1 (20.90.10) and it seems to run OK.

Whoever wrote the Linux build script(s) and associated documentation deserves a big 'Thank You'.  Apart from a brief self-induced Wayland dependency digression, the build process worked perfectly for X11 on the first attempt.

I discovered that the Python xbmc.getRegion() function comes from 'xbmc-master/xbmc/interfaces/legacy/ModuleXbmc.cpp -> getRegion' so this is the function that I updated.

I have made the changes to 'GetAsLocalizedDate' that I mentioned previously so that it can now either return a formatted date string or a formatting string.

'getRegion' has also been updated to use the new version of 'GetAsLocalizedDate' and the modifications seem to be working as intended.  I also added 3 new keywords 'datelongraw', 'dateshortraw' and 'timeraw' that return the raw XML formatting string.

This is all well and good on my stand-alone development system, now I need to investigate the process for submitting the changes for consideration in the next release as well as comprehensive testing.
Reply

Logout Mark Read Team Forum Stats Members Help
Changing Date Format to 'DD-MMM-YY'0