Repository navigation
Get-Date -UFormat inconsistencies compared to Linux strftime #4750
Description
With reference to #4264 first reported by chuanjiao10 - on further examination there are a number of UFormats outputs which diverge from the output under Linux. Because the UFormat parameter is supposed to be UNIX format, the output should match that of the date command (i.e. strftime) on Linux.
It's clear that some of the divergences are simple format issues, for instance leading zeros. Others are down to following the ISO 8601 week date specification (https://en.wikipedia.org/wiki/ISO_week_date). And others appear to be differences between locale data on Linux and .Net. In these latter cases it looks like the C locale is followed, which may actually be the best that can be done given the lack of Linux locale data.
%c
- (PR Correct %c, %l, %k, %s, %j format in Get-Date -UFormat #4805) The preferred date and time representation for the current locale.
en-US
PowerShell
[System.Threading.Thread]::CurrentThread.CurrentCulture = [System.Globalization.CultureInfo]::GetCultureInfo('en-US')
get-date -Year 2005 -Month 1 -Day 1 -Hour 1 -Minute 0 -Second 0 -UFormat %c Sat Jan 1 01:00:00 2005
Linux
LC_TIME="en_US.UTF-8" date -d 2005-01-01T01:00:00 +%cSat 01 Jan 2005 01:00:00 AM GMT
C
PowerShell
[System.Threading.Thread]::CurrentThread.CurrentCulture = [System.Globalization.CultureInfo]::GetCultureInfo('en-US')
get-date -Year 2005 -Month 1 -Day 1 -Hour 1 -Minute 0 -Second 0 -UFormat %c Sat Jan 1 01:00:00 2005
Linux
LC_TIME="C.UTF-8" date -d 2005-01-01T01:00:00 +%cSat Jan 1 01:00:00 2005
%g
- (PR #4750 Fix Get-Date -UFormat %G and %g behavior #14555) Like %G, but without century, that is, with a 2-digit year (00-99).
en-US
PowerShell
[System.Threading.Thread]::CurrentThread.CurrentCulture = [System.Globalization.CultureInfo]::GetCultureInfo('en-US')
get-date -Year 2005 -Month 1 -Day 1 -Hour 1 -Minute 0 -Second 0 -UFormat %g 05
Linux
LC_TIME="en_US.UTF-8" date -d 2005-01-01T01:00:00 +%g04
%G
- (PR #4750 Fix Get-Date -UFormat %G and %g behavior #14555) The ISO 8601 week-based year ... with century as a decimal number.
en-US
PowerShell
[System.Threading.Thread]::CurrentThread.CurrentCulture = [System.Globalization.CultureInfo]::GetCultureInfo('en-US')
get-date -Year 2005 -Month 1 -Day 1 -Hour 1 -Minute 0 -Second 0 -UFormat %g 2005
Linux
LC_TIME="en_US.UTF-8" date -d 2005-01-01T01:00:00 +%G2004
%j
- (PR Correct %c, %l, %k, %s, %j format in Get-Date -UFormat #4805) The day of the year as a decimal number (range 001 to 366).
en-US
PowerShell
[System.Threading.Thread]::CurrentThread.CurrentCulture = [System.Globalization.CultureInfo]::GetCultureInfo('en-US')
get-date -Year 2005 -Month 1 -Day 1 -Hour 1 -Minute 0 -Second 0 -UFormat %j 1
Linux
LC_TIME="en_US.UTF-8" date -d 2005-01-01T01:00:00 +%j001
%k
- (PR Correct %c, %l, %k, %s, %j format in Get-Date -UFormat #4805) The hour (24-hour clock) as a decimal number (range 0 to 23); single digits are preceded by a blank.
en-US
PowerShell
[System.Threading.Thread]::CurrentThread.CurrentCulture = [System.Globalization.CultureInfo]::GetCultureInfo('en-US')
get-date -Year 2005 -Month 1 -Day 1 -Hour 1 -Minute 0 -Second 0 -UFormat %k 01
Linux
LC_TIME="en_US.UTF-8" date -d 2005-01-01T01:00:00 +%k 1
%l
- (PR Correct %c, %l, %k, %s, %j format in Get-Date -UFormat #4805) The hour (12-hour clock) as a decimal number (range 1 to 12); single digits are preceded by a blank.
en-US
PowerShell
[System.Threading.Thread]::CurrentThread.CurrentCulture = [System.Globalization.CultureInfo]::GetCultureInfo('en-US')
get-date -Year 2005 -Month 1 -Day 1 -Hour 1 -Minute 0 -Second 0 -UFormat %l 01
Linux
LC_TIME="en_US.UTF-8" date -d 2005-01-01T01:00:00 +%l 1
%s
- (PR Correct %c, %l, %k, %s, %j format in Get-Date -UFormat #4805) The number of seconds since the Epoch, 1970-01-01 00:00:00+0000 (UTC).
en-US
PowerShell
[System.Threading.Thread]::CurrentThread.CurrentCulture = [System.Globalization.CultureInfo]::GetCultureInfo('en-US')
get-date -Year 2005 -Month 1 -Day 1 -Hour 1 -Minute 0 -Second 0 -Millisecond 0 -UFormat %s 1104541200
Linux
LC_TIME="en_US.UTF-8" date -d 2005-01-01T01:00:00 +%s1104541200
[System.Threading.Thread]::CurrentThread.CurrentCulture = [System.Globalization.CultureInfo]::GetCultureInfo('en-US')
get-date -Year 2005 -Month 1 -Day 1 -Hour 1 -Minute 0 -Second 0 -Millisecond 1 -UFormat %s 1104541200.001
Linux
LC_TIME="en_US.UTF-8" date -d 2005-01-01T01:00:00.001 +%s 1104541200
%u
- (PR #4750 Fix Get-Date -UFormat %u behavior #14549) The ISO 8601 day of the week 1-7 (M-Su).
en-US
PowerShell
[System.Threading.Thread]::CurrentThread.CurrentCulture = [System.Globalization.CultureInfo]::GetCultureInfo('en-US')
get-date -Year 2005 -Month 1 -Day 2 -Hour 1 -Minute 0 -Second 0 -UFormat %u0
Linux
LC_TIME="en_US.UTF-8" date -d 2005-01-02T01:00:00 +%u7
%U
- The week number of the current year as a decimal number, range 00 to 53, starting with the first Sunday as the first day of week 01.
en-US
PowerShell
[System.Threading.Thread]::CurrentThread.CurrentCulture = [System.Globalization.CultureInfo]::GetCultureInfo('en-US')
get-date -Year 2005 -Month 1 -Day 1 -Hour 1 -Minute 0 -Second 0 -UFormat %U 0
Linux
LC_TIME="en_US.UTF-8" date -d 2005-01-01T01:00:00 +%U00
%V
- The ISO 8601 week number ... of the current year as a decimal number, range 01 to 53, where week 1 is the first week that has at least 4 days in the new year.
en-US
PowerShell
[System.Threading.Thread]::CurrentThread.CurrentCulture = [System.Globalization.CultureInfo]::GetCultureInfo('en-US')
get-date -Year 2005 -Month 1 -Day 1 -Hour 1 -Minute 0 -Second 0 -UFormat %V 1
Linux
LC_TIME="en_US.UTF-8" date -d 2005-01-01T01:00:00 +%V53
%W
- The week number of the current year as a decimal number, range 00 to 53, starting with the first Monday as the first day of week 01.
en-US
PowerShell
[System.Threading.Thread]::CurrentThread.CurrentCulture = [System.Globalization.CultureInfo]::GetCultureInfo('en-US')
get-date -Year 2005 -Month 1 -Day 1 -Hour 1 -Minute 0 -Second 0 -UFormat %W 0
Linux
LC_TIME="en_US.UTF-8" date -d 2005-01-01T01:00:00 +%W00
%x
- The preferred date representation for the current locale without the time.
en-US
PowerShell
[System.Threading.Thread]::CurrentThread.CurrentCulture = [System.Globalization.CultureInfo]::GetCultureInfo('en-US')
get-date -Year 2005 -Month 1 -Day 1 -Hour 1 -Minute 0 -Second 0 -UFormat %x 01/01/05
Linux
LC_TIME="en_US.UTF-8" date -d 2005-01-01T01:00:00 +%x01/01/2005
C
PowerShell
[System.Threading.Thread]::CurrentThread.CurrentCulture = [System.Globalization.CultureInfo]::GetCultureInfo('en-US')
get-date -Year 2005 -Month 1 -Day 1 -Hour 1 -Minute 0 -Second 0 -UFormat %x 01/01/05
Linux
LC_TIME="C.UTF-8" date -d 2005-01-01T01:00:00 +%x01/01/05
%X
- The preferred date representation for the current locale without the time.
en-US
PowerShell
[System.Threading.Thread]::CurrentThread.CurrentCulture = [System.Globalization.CultureInfo]::GetCultureInfo('en-US')
get-date -Year 2005 -Month 1 -Day 1 -Hour 1 -Minute 0 -Second 0 -UFormat %X 01:00:00
Linux
LC_TIME="en_US.UTF-8" date -d 2005-01-01T01:00:00 +%X01:00:00 AM
C
PowerShell
[System.Threading.Thread]::CurrentThread.CurrentCulture = [System.Globalization.CultureInfo]::GetCultureInfo('en-US')
get-date -Year 2005 -Month 1 -Day 1 -Hour 1 -Minute 0 -Second 0 -UFormat %X 01:00:00
Linux
LC_TIME="C.UTF-8" date -d 2005-01-01T01:00:00 +%X01:00:00
%Z
- The timezone name or abbreviation.
en-US
PowerShell
[System.Threading.Thread]::CurrentThread.CurrentCulture = [System.Globalization.CultureInfo]::GetCultureInfo('en-US')
get-date -Year 2005 -Month 1 -Day 1 -Hour 1 -Minute 0 -Second 0 -UFormat %Z +00
Linux
LC_TIME="en_US.UTF-8" date -d 2005-01-01T01:00:00 +%ZGMT
> $PSVersionTable
Name Value
---- -----
PSVersion 6.0.0-beta
PSEdition Core
GitCommitId v6.0.0-beta.5
OS Linux 4.10.0-32-generic #36~16.04.1-Ubuntu SM...
Platform Unix
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0 I initially, naively, made PR #4508 for #4264 which simply used the GetWeekOfYear method from the Gregorian Calendar. Unfortunately that is too simplistic, and the formula needs to be followed to determine the correct week number. I suggest that PR be closed and new PRs to be created against this tracking issue. My suggestion is that the Pester tests be broken out into a test per UFormat to make this easier (with the failing tests commented until they can be addressed).
Activity
[-]Get-Date -UFormat inconsitencies compared to Linux strftime[/-][+]Get-Date -UFormat inconsistencies compared to Linux strftime[/+]iSazonov commentedon Sep 4, 2017
It seems the formatting can differ between different Linux distributions (I tested on WSL) so I would exclude such points from the Issue.
Please reformat the Issue.
timparkinson commentedon Sep 4, 2017
I've checked on Ubuntu 14.04, Ubuntu 16.04 and CentOS 7 machines and the formatting is consistent between them. I don't have a machine with WSL on it handy at the moment to test. Furthermore, the descriptions of the format codes in the strftime man pages do specify format. For instance %k - Get-Date current behaviour is to output with a leading zero, whereas per stfrtime man page:
What formatting changes do you want me to make to the issue?
iSazonov commentedon Sep 4, 2017
It is difficult to read the Issue description 😕
Steve Lee (@SteveL-MSFT) Should we fix the formattings? Do PowerShell-Committee conclusion in #4508 cover this?
SteveL-MSFT commentedon Sep 4, 2017
Is there a RFC or something more canonical than specific distro implementations we can refer to?
iSazonov commentedon Sep 5, 2017
I found https://tools.ietf.org/html/rfc3339#page-12
SteveL-MSFT commentedon Sep 5, 2017
Regarding formatting of the issue, I can read each format and the comparison between PowerShell and Linux, so it seems readable enough to me. Ilya (@iSazonov) if you have a suggestion on how to make this more readable, feel free to offer it. It's just long which makes it difficult, but probably better than having multiple separate issues. Per the ietf link, I believe we should be prefixing with zeros so that there's always two digits, but I'm no expert on this topic.
iSazonov commentedon Sep 5, 2017
I slightly reformatted.
I agree that we only need the one Issue. Based on #4508 long discussion it seems better to fix each position in a separate PR where discuss, fix and add tests.
SteveL-MSFT commentedon Sep 5, 2017
Ilya (@iSazonov) agree that it would be better to have separate PRs making it easier to review. Also, are these all things we should change in PowerShell or should they be changes in corefx? Some formats I believe the cmdlet implements, but some come from corefx.
iSazonov commentedon Sep 5, 2017
I don't analyze all but it seems most should be fixed in PowerShell repo.
iSazonov commentedon Sep 7, 2017
Open #4796 to fix %c.
iSazonov commentedon Sep 11, 2017
Open #4805 to fix %j.
brianary commentedon Jan 5, 2021
The
%uformat specifier should also be included. ISO says Sunday is 7, not 0.%u
The ISO 8601 day of the week 1-7 (M-Su).
en-US
PowerShell
Linux
LC_TIME="en_US.UTF-8" date -d 2005-01-02T01:00:00 +%uThis is important in order to format an accurate ISO8601 week date 📺, using
%G-W%V-%u, which all have to work consistently with each other.%G-W%V-%u
The ISO 8601 week-based date.
en-US
PowerShell
Linux
LC_TIME="en_US.UTF-8" date -d 2021-01-03T01:00:00 +%G-W%V-%u8 remaining items
microsoft-github-policy-service commentedon Nov 16, 2023
This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.
microsoft-github-policy-service commentedon Nov 16, 2023
This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.
microsoft-github-policy-service commentedon Nov 16, 2023
This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.
brianary commentedon Nov 17, 2023
It looks like there is more work to do, just based on a quick test of the value
2023-11-14T14:13:20-08:dateGet-Date -UFormat%cTue Nov 14 14:13:20 2023Tue 14 Nov 2023 14:13:20%D11/14/2311-14-23%f000000f%U4645%W4645%x11/14/2311-14-23%Z-08Z%z-0800z%:z-08:00:z%::z-08:00:00::z%:::z-08:::zbrianary commentedon Nov 19, 2023
It looks like
%ealso fails at times. Here are some examples of the 12 failing format specifiers:Some
Get-Date -UnixTimeSeconds $Epoch -UFormat "%$Format"valuesthat don't match
date --date="@$Epoch" "+%$Format":::z-07:::z:::z-07:::z:::z-08:::z:::z-07:::z:::z-07:::z:::z-07:::z:::z-07:::z:::z-08:::z:::z-07:::z:::z-07:::z:::z-08:::z:::z-08:::z:::z-07:::z:::z-07:::z:::z-07:::z:::z-07:::z:::z-07:::z:::z-07:::z:::z-07:::z:::z-07:::z::z-07:00:00::z::z-07:00:00::z::z-08:00:00::z::z-07:00:00::z::z-07:00:00::z::z-07:00:00::z::z-07:00:00::z::z-08:00:00::z::z-07:00:00::z::z-07:00:00::z::z-08:00:00::z::z-08:00:00::z::z-07:00:00::z::z-07:00:00::z::z-07:00:00::z::z-07:00:00::z::z-07:00:00::z::z-07:00:00::z::z-07:00:00::z::z-07:00:00::z:z-07:00:z:z-07:00:z:z-08:00:z:z-07:00:z:z-07:00:z:z-07:00:z:z-07:00:z:z-08:00:z:z-07:00:z:z-07:00:z:z-08:00:z:z-08:00:z:z-07:00:z:z-07:00:z:z-07:00:z:z-07:00:z:z-07:00:z:z-07:00:z:z-07:00:z:z-07:00:zcSat Oct 27 17:45:46 2007Sat 27 Oct 2007 17:45:46cMon Sep 22 19:49:34 2014Mon 22 Sep 2014 19:49:34cSat Dec 3 16:22:04 2005Sat 03 Dec 2005 16:22:04cThu Sep 11 22:24:40 2003Thu 11 Sep 2003 22:24:40cWed May 24 11:00:25 2000Wed 24 May 2000 11:00:25cThu May 16 06:54:10 2013Thu 16 May 2013 06:54:10cTue Aug 19 02:26:34 2008Tue 19 Aug 2008 02:26:34cThu Feb 9 14:03:46 2023Thu 09 Feb 2023 14:03:46cSat Aug 16 07:53:55 2014Sat 16 Aug 2014 07:53:55cWed May 3 19:51:58 2000Wed 03 May 2000 19:51:58cFri Feb 28 15:01:55 2014Fri 28 Feb 2014 15:01:55cWed Jan 12 07:05:01 2000Wed 12 Jan 2000 07:05:01cSat Aug 23 11:15:13 2008Sat 23 Aug 2008 11:15:13cFri Oct 10 16:43:01 2003Fri 10 Oct 2003 16:43:01cWed Oct 26 21:55:04 2022Wed 26 Oct 2022 21:55:04cFri Mar 28 16:16:01 2014Fri 28 Mar 2014 16:16:01cTue Sep 10 23:41:31 2019Tue 10 Sep 2019 23:41:31cFri Jul 8 17:50:13 2016Fri 08 Jul 2016 17:50:13cSun Jun 20 17:31:19 2021Sun 20 Jun 2021 17:31:19cFri Jul 31 23:03:49 2020Fri 31 Jul 2020 23:03:49D10/27/0710-27-07D09/22/1409-22-14D12/03/0512-03-05D09/11/0309-11-03D05/24/0005-24-00D05/16/1305-16-13D08/19/0808-19-08D02/09/2302-09-23D08/16/1408-16-14D05/03/0005-03-00D02/28/1402-28-14D01/12/0001-12-00D08/23/0808-23-08D10/10/0310-10-03D10/26/2210-26-22D03/28/1403-28-14D09/10/1909-10-19D07/08/1607-08-16D06/20/2106-20-21D07/31/2007-31-20e33e99e33e88e88e55e66e88e55e55e22e77e88e44e11e55e22e55e33e33f%fff%fff%fff%fff%fff%fff%fff%fff%fff%fff%fff%fff%fff%fff%fff%fff%fff%fff%fff%ffU3837U2120U065U1817U088U021U4342U2524U032U2120U3736U4443U099U4039U033U022U077U2726U098U4948W4342W3837W2120W065W1817W088W021W4342W032W109W2625W4544W033W022W077W2726W3332W088W4948W2019x10/27/0710-27-07x09/22/1409-22-14x12/03/0512-03-05x09/11/0309-11-03x05/24/0005-24-00x05/16/1305-16-13x08/19/0808-19-08x02/09/2302-09-23x08/16/1408-16-14x05/03/0005-03-00x02/28/1402-28-14x01/12/0001-12-00x08/23/0808-23-08x10/10/0310-10-03x10/26/2210-26-22x03/28/1403-28-14x09/10/1909-10-19x07/08/1607-08-16x06/20/2106-20-21x07/31/2007-31-20ZPDT-07z-0700zz-0700zZPDT-07ZPST-08z-0800zZPDT-07z-0700zz-0700zZPDT-07z-0700zZPDT-07ZPDT-07z-0700zZPST-08z-0800zz-0700zZPDT-07z-0700zZPDT-07brianary commentedon Nov 20, 2023
%cdiffers by the order of the fields; it doesn't match the POSIX format, but since this format is defined as "The preferred date and time representation for the current locale", there may be some flexibility there.%Dand%xdiffer only by the date separator, which could be due to Windows locale settings. The former indicates a specific separator to use, so it should be changed from using the user-preferred separator to the fixed one. Since the latter is defined as "Locale’s appropriate date representation", there may be some flexibility for that one.%elooks fine; the leading space seems to have confused some testing.%fisn't a format character.%Uand%Wweek numbers seem to be off by one for many (all?) dates. These are the only ones providing numerically incorrect data.%Z%z%:z%::z%:::zthe time zone formats all need work, though%Zis "The timezone name or abbreviation", which suggests some flexibility. The rest are unimplemented.microsoft-github-policy-service commentedon Nov 27, 2023
This issue has been marked as "No Activity" as there has been no activity for 6 months. It has been closed for housekeeping purposes.
✅ Add tests for Get-Date -UFormat
PowerShell#4750 Fix Get-Date -UFormat %u behavior (PowerShell#14549)
PowerShell#4750 Fix Get-Date -UFormat %G and %g behavior (PowerShell#…