It is currently February 25th, 2021, 11:02 pm

[Bug?] Proper %D formatting with FormatLocale for different regions

Report bugs with the Rainmeter application and suggest features.
User avatar
Cariboudjan
Posts: 131
Joined: May 12th, 2019, 8:55 am

[Bug?] Proper %D formatting with FormatLocale for different regions

Post by Cariboudjan »

Code: Select all

[MeasureDate]
Measure=Time
Format="%D"
FormatLocale=#LanguageCode#
DynamicVariables=1
%D doesn't appear to format correctly for different regions. January 17, 2021 formats as 17/01/21 despite the US being the only actual place that formats MONTH/DAY/YEAR. Japan for example, formats YEAR/MONTH/DAY, and most areas of Europe format DAY/MONTH/YEAR.

Btw, Canada formats DAY/MONTH/YEAR despite what Wikipedia says. No one in Canada uses YEAR/MONTH/DAY, yet that's what it says Canada uses on Wikipedia for some reason. :confused:

This might be a Windows thing, but if it isn't, this probably requires a fix. Maybe changing the formatting in Windows fixes this. I don't know, but it's strange that FormatLocale doesn't override the Windows setting.

https://en.wikipedia.org/wiki/Date_format_by_country
User avatar
balala
Rainmeter Sage
Posts: 12279
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: [Bug?] Proper %D formatting with FormatLocale for different regions

Post by balala »

Cariboudjan wrote: January 17th, 2021, 6:56 pm %D doesn't appear to format correctly for different regions. January 17, 2021 formats as 17/01/21 despite the US being the only actual place that formats MONTH/DAY/YEAR. Japan for example, formats YEAR/MONTH/DAY, and most areas of Europe format DAY/MONTH/YEAR.
If you read carfully the description in the help page of Time measures, at the Format codes, you can see that %D means:
%D: Short MM/DD/YY date, equivalent to %m/%d/%y (e.g. "12/26/15")
This format ALWAYS returns the date in the specified format (MM/DD/YY), no matter what FormatLocale do you set.
BTW, what is the value of the LanguageCode variable you've used?
User avatar
Cariboudjan
Posts: 131
Joined: May 12th, 2019, 8:55 am

Re: [Bug?] Proper %D formatting with FormatLocale for different regions

Post by Cariboudjan »

Well the locale is irrelevant since it doesn't affect %D. Why shouldn't %D be language-specific? Vast majority of the world does not use MM/DD/YY.

Could be MM/DD/YY by default since it is a US app, but any locale other than en-us should be DD/MM/YY unless China, Japan, or Korea, in which case YY/MM/DD.
User avatar
balala
Rainmeter Sage
Posts: 12279
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: [Bug?] Proper %D formatting with FormatLocale for different regions

Post by balala »

Cariboudjan wrote: January 18th, 2021, 2:14 am Well the locale is irrelevant since it doesn't affect %D. Why shouldn't %D be language-specific? Vast majority of the world does not use MM/DD/YY.
You might be right, however that's it. But you can easily use another format, for instance Format=%F, which is:
%F: Short YYYY-MM-DD date, equivalent to %Y-%m-%d (e.g. "2015-12-26")
Or if needed, you can set specifically the required format and this solution doesn't have such limitations. Format=%d-%m-%y or whatever you do want.
Cariboudjan wrote: January 18th, 2021, 2:14 am Could be MM/DD/YY by default since it is a US app, but any locale other than en-us should be DD/MM/YY unless China, Japan, or Korea, in which case YY/MM/DD.
Not entirely. For example what I know for sure: in Romanian we're using DD.MM.YYYY, while in Hungarian exactly vice-versa: YYYY.MM.DD. Threre probably isn't a general format, which can be used everywhere, not even for a smaller region.
Wim
Posts: 69
Joined: September 22nd, 2010, 8:30 pm

Re: [Bug?] Proper %D formatting with FormatLocale for different regions

Post by Wim »

I would think that what you probably are looking for is %c or %x

Code: Select all

[MeasureDate]
Measure=Time
Format=%c
FormatLocale=Local
Using %c on my computer (dutch) i get:
Local.PNG
Using %x i get
Local2.PNG
%c should give a format with "... the language defined by the locale, but also with the appropriate order, structure and punctuation."

See:
https://docs.rainmeter.net/manual/measures/time/#FormatLocale
You do not have the required permissions to view the files attached to this post.
User avatar
balala
Rainmeter Sage
Posts: 12279
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: [Bug?] Proper %D formatting with FormatLocale for different regions

Post by balala »

Wim wrote: January 18th, 2021, 12:10 pm I would think that what you probably are looking for is %c
Format=%c returns, beside the date, the time as well, which has not been asked. That's why I proposed Format=%F.
Wim
Posts: 69
Joined: September 22nd, 2010, 8:30 pm

Re: [Bug?] Proper %D formatting with FormatLocale for different regions

Post by Wim »

%F gives
Local3.PNG
which is not really the local format where i live (though we do use it on occasion)

I've added %x to my original post because that one does not show the time - just the date - and in the local format.
You do not have the required permissions to view the files attached to this post.
User avatar
balala
Rainmeter Sage
Posts: 12279
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: [Bug?] Proper %D formatting with FormatLocale for different regions

Post by balala »

Wim wrote: January 18th, 2021, 12:44 pm I've added %x to my original post because that one does not show the time - just the date - and in the local format.
Good solution, I suppose. Is it good enough?
If it's not, you probably should have to use specific formats, something like Format=%d/%m/%Y or Format=%d/%m/%y. Both are returning the date in Day/Month/Year format, but while the first one writes the full year (with four digits), the second one writes it with only two digits (without the century).
But if Format=%x is alright, it can be used as well.
User avatar
SilverAzide
Rainmeter Sage
Posts: 1134
Joined: March 23rd, 2015, 5:26 pm

Re: [Bug?] Proper %D formatting with FormatLocale for different regions

Post by SilverAzide »

Cariboudjan wrote: January 17th, 2021, 6:56 pm %D doesn't appear to format correctly for different regions. January 17, 2021 formats as 17/01/21 despite the US being the only actual place that formats MONTH/DAY/YEAR. Japan for example, formats YEAR/MONTH/DAY, and most areas of Europe format DAY/MONTH/YEAR.

Btw, Canada formats DAY/MONTH/YEAR despite what Wikipedia says. No one in Canada uses YEAR/MONTH/DAY, yet that's what it says Canada uses on Wikipedia for some reason. :confused:

This might be a Windows thing, but if it isn't, this probably requires a fix. Maybe changing the formatting in Windows fixes this. I don't know, but it's strange that FormatLocale doesn't override the Windows setting.
Sorry to interject here at this late point, but if proper date and time formatting is important to your skin, I would suggest considering an alternate approach. It requires a little more work, but it's almost guaranteed (but not 100% guaranteed) to give the exact results your end-user wants to see.

The problem is that while Rainmeter (and Lua) do support formatting by locale, you've discovered that not all locales are correct. There are cases where the Y/M/D order is off, cases where the separator is off, and cases where both are off. Not only that, maybe the formatting is perfect, but the user has decided he prefers something else that is non-standard for that locale.

It turns out that the Windows registry contains the exact formatting strings needed to properly format the date and time the way the locale and/or user wants to see it. The problem is that Windows uses a format style that is completely different than Rainmeter/Lua, so you need to do a little substitution work to translate the format string from Windows-style to Rainmeter-style. But once you do the work, you'll have a format string that will almost always be exactly what the user wants to see, regardless of any locale.

Code: Select all

[Rainmeter]
AccurateText=1
DynamicWindowSize=1
Update=1000

[Variables]
; set default values; these are dynamic so no need to change them here
MyLongDateFormat=""
MyShortDateFormat=""
MyLongTimeFormat=""
MyShortTimeFormat=""

; -----------------------------------------------------------------------------
; Measures
; -----------------------------------------------------------------------------

; sLongDate = "dddd, MMMM d, yyyy" (example)
;   yyyyy = 5-digit year (00001-99999)          = no equivalent in Rainmeter, use %Y
;   yyyy = 4-digit year (0001-9999)             = %Y
;   yyy  = 3-digit year (001-999)               = no equivalent in Rainmeter, use %#Y
;   yy   = 2-digit year (01-99)                 = %y
;   y    = 1-digit year (1-99)                  = no equivalent in Rainmeter, use %#y
;   MMMM = month name ("August")                = %B
;   MMM  = abbreviated month name ("Aug")       = %b
;   MM   = month number, leading zero (01-12)   = %m
;   M    = month number, no leading zero (1-12) = %#m
;   dddd = day name ("Friday")                  = %A
;   ddd  = abbreviated day name ("Fri")         = %a
;   dd   = day number, leading zero (01-31)     = %d
;   d    = day number, no leading zero (1-31)   = %#d
;
[MeasureLongDateFormat]
Measure=Registry
RegHKey=HKEY_CURRENT_USER
RegKey=Control Panel\International
RegValue=sLongDate
Substitute="y":"@","@@@@@":"%Y","@@@@":"%Y","@@@":"%#Y","@@":"%y","@":"%#y","M":"@","@@@@":"%B","@@@":"%b","@@":"%m","@":"%#m","d":"@","@@@@":"%A","@@@":"%a","@@":"%d","@":"%#d"
IfMatch="^#MyLongDateFormat#$"
IfNotMatchAction=[!SetVariable MyLongDateFormat "[MeasureLongDateFormat]"][!UpdateMeasure MeasureLongDate][!Redraw]
DynamicVariables=1
; use UpdateDivider=-1 so measures run once on load/refresh; remove if you want skin to react to format changes
UpdateDivider=-1

; sShortDate = "M/d/yyyy" (example)
[MeasureShortDateFormat]
Measure=Registry
RegHKey=HKEY_CURRENT_USER
RegKey=Control Panel\International
RegValue=sShortDate
Substitute="y":"@","@@@@@":"%Y","@@@@":"%Y","@@@":"%#Y","@@":"%y","@":"%#y","M":"@","@@@@":"%B","@@@":"%b","@@":"%m","@":"%#m","d":"@","@@@@":"%A","@@@":"%a","@@":"%d","@":"%#d"
IfMatch="^#MyShortDateFormat#$"
IfNotMatchAction=[!SetVariable MyShortDateFormat "[MeasureShortDateFormat]"][!UpdateMeasure MeasureShortDate][!Redraw]
DynamicVariables=1
UpdateDivider=-1

; sTimeFormat = "h:mm:ss tt" (example)
;   HH = hour, zero-based 24-hour, leading zero (00-23)   = %H
;   H  = hour, zero-based 24-hour, no leading zero (0-23) = %#H
;   hh = hour, 12-hour, leading zero (01-12)              = %I
;   h  = hour, 12-hour, no leading zero (1-12)            = %#I
;   mm = minute, leading zero (00-59)                     = %M
;   m  = minute, no leading zero (0-59)                   = %#M
;   ss = seconds, leading zero (00-59)                    = %S
;   s  = seconds, no leading zero (0-59)                  = %#S
;   tt = AM/PM designator                                 = %p
;   t  = abbreviated AM/PM designator (A/P)               = no equivalent in Rainmeter, use %p
;
[MeasureLongTimeFormat]
Measure=Registry
RegHKey=HKEY_CURRENT_USER
RegKey=Control Panel\International
RegValue=sTimeFormat
Substitute="H":"@","@@":"%H","@":"%#H","h":"@","@@":"%I","@":"%#I","m":"@","@@":"%M","@":"%#M","s":"@","@@":"%S","@":"%#S","t":"@","@@":"%p","@":"%p"
IfMatch="^#MyLongTimeFormat#$"
IfNotMatchAction=[!SetVariable MyLongTimeFormat "[MeasureLongTimeFormat]"][!UpdateMeasure MeasureLongTime][!Redraw]
DynamicVariables=1
UpdateDivider=-1

; sShortTime = "h:mm tt" (example)
[MeasureShortTimeFormat]
Measure=Registry
RegHKey=HKEY_CURRENT_USER
RegKey=Control Panel\International
RegValue=sShortTime
Substitute="H":"@","@@":"%H","@":"%#H","h":"@","@@":"%I","@":"%#I","m":"@","@@":"%M","@":"%#M","s":"@","@@":"%S","@":"%#S","t":"@","@@":"%p","@":"%p"
IfMatch="^#MyShortTimeFormat#$"
IfNotMatchAction=[!SetVariable MyShortTimeFormat "[MeasureShortTimeFormat]"][!UpdateMeasure MeasureShortTime][!Redraw]
DynamicVariables=1
UpdateDivider=-1

[MeasureLongDate]
Measure=Time
; the two Format options are equivalent; use whichever you prefer
Format=[MeasureLongDateFormat]
;Format=#MyLongDateFormat#
FormatLocale=Local
DynamicVariables=1

[MeasureShortDate]
Measure=Time
Format=[MeasureShortDateFormat]
;Format=#MyShortDateFormat#
DynamicVariables=1

[MeasureLongTime]
Measure=Time
Format=[MeasureLongTimeFormat]
;Format=#MyLongTimeFormat#
DynamicVariables=1

[MeasureShortTime]
Measure=Time
Format=[MeasureShortTimeFormat]
;Format=#MyShortTimeFormat#
DynamicVariables=1

; -----------------------------------------------------------------------------
; Meters
; -----------------------------------------------------------------------------

[MeterTest]
Meter=String
MeasureName=MeasureLongTime
MeasureName2=MeasureLongDate
FontColor=255,255,255
SolidColor=0,0,0
Text="It is %1 on %2."
I threw extra code in the example if you prefer using variables instead of measures, but the result is equivalent. (If you are wondering about the weird "@" substitutions, you can get into cases where the substitutions don't work properly if you try straight-up replacements, so I first change the values to an unused character [I chose "@"], then do substitutions on that character.)

Note that I said "almost guaranteed (but not 100% guaranteed)"... Turns out that some of the registry formatting settings might not be correct if the user decides to override the formats with something odd, like using "~" or something goofy as a separator. If you care enough to want to handle edge cases, then you can grab the registry key values for "iDate" and "iTime" which are integer values that describe the format, along with "sDate" and "sTime" which are the separators, and "iLZero" which tells you if the user wants leading zeros, then use all these values to reconstruct the entire format string yourself, ignoring the formatting strings in the registry. It's additional work, but you only have to do it once...
Gadgets Wiki GitHub More Gadgets...
Wim
Posts: 69
Joined: September 22nd, 2010, 8:30 pm

Re: [Bug?] Proper %D formatting with FormatLocale for different regions

Post by Wim »

Ingenious

I've got one thing though (and i hope you don't mind). It all comes out in English. It's easy to fix (i added FormatLocale=Local to MeasureLongDate) but it has me surprised. My computer is set to dutch yet the long date is given in English. If correct formatting is the point wouldn't language have to be a part of it?