From 3d05953dd332d55046212dc16481114f5491d433 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Ferenc=20Nagy-Egri?= Date: Mon, 13 Oct 2025 17:49:12 +0200 Subject: [PATCH 1/3] Fix LastWriteTime formatting on Unix and locales with wide DateTimeFormat --- .../DefaultFormatters/FileSystem_format_ps1xml.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/FileSystem_format_ps1xml.cs b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/FileSystem_format_ps1xml.cs index 0400f99b899..16fc8c2a524 100644 --- a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/FileSystem_format_ps1xml.cs +++ b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/FileSystem_format_ps1xml.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System.Collections.Generic; +using System.Globalization; namespace System.Management.Automation.Runspaces { @@ -48,7 +49,9 @@ private static IEnumerable ViewsOf_FileSystemTypes(CustomC .AddHeader(Alignment.Left, label: "UnixMode", width: 10) .AddHeader(Alignment.Right, label: "User", width: 10) .AddHeader(Alignment.Left, label: "Group", width: 10) - .AddHeader(Alignment.Right, label: "LastWriteTime", width: 16) + // Until LastWriteTime prints as '{0:d} {0:HH}:{0:mm}', it will always be local date + 6 wide. + // https://github.com/PowerShell/PowerShell/issues/19723 + .AddHeader(Alignment.Right, label: "LastWriteTime", width: CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern.Length + 6) .AddHeader(Alignment.Right, label: "Size", width: 12) .AddHeader(Alignment.Left, label: "Name") .StartRowDefinition(wrap: true) From b91574cb4c458423db92ec95ef4b4ef77d0adc74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Ferenc=20Nagy-Egri?= Date: Tue, 14 Oct 2025 21:35:50 +0200 Subject: [PATCH 2/3] Fix LastWriteTime formatting on Unix for all non-arabic locales --- .../DefaultFormatters/FileSystem_format_ps1xml.cs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/FileSystem_format_ps1xml.cs b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/FileSystem_format_ps1xml.cs index 16fc8c2a524..75548e1f61a 100644 --- a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/FileSystem_format_ps1xml.cs +++ b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/FileSystem_format_ps1xml.cs @@ -49,9 +49,20 @@ private static IEnumerable ViewsOf_FileSystemTypes(CustomC .AddHeader(Alignment.Left, label: "UnixMode", width: 10) .AddHeader(Alignment.Right, label: "User", width: 10) .AddHeader(Alignment.Left, label: "Group", width: 10) - // Until LastWriteTime prints as '{0:d} {0:HH}:{0:mm}', it will always be local date + 6 wide. + // Until LastWriteTime prints as '{0:d} {0:HH}:{0:mm}', it will always be ShortDatePattern + 6 wide. + // Some locale's ShortDatePattern don't trivially relate to the length of the serialized date string. + // Some patterns only have a single day or month designator but will likely take 2 characters, and + // some even have era designators in their ShortDatePattern, which we take the length of and 1 extra + // for a space character. The Fixed 6 comes from the time suffix, eg. " 23:59". // https://github.com/PowerShell/PowerShell/issues/19723 - .AddHeader(Alignment.Right, label: "LastWriteTime", width: CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern.Length + 6) + .AddHeader( + Alignment.Right, + label: "LastWriteTime", + width: CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern.Length + + (CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern.AsSpan().Count('d') == 1 ? 1 : 0) + + (CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern.AsSpan().Count('M') == 1 ? 1 : 0) + + (CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern.AsSpan().Count('g') == 1 ? 1 + CultureInfo.CurrentCulture.DateTimeFormat.GetEraName(1).Length : 0) + + 6) .AddHeader(Alignment.Right, label: "Size", width: 12) .AddHeader(Alignment.Left, label: "Name") .StartRowDefinition(wrap: true) From c724e51797d45ebba16a8109721a4ff384f25806 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Ferenc=20Nagy-Egri?= Date: Wed, 15 Oct 2025 11:28:18 +0200 Subject: [PATCH 3/3] Simplify formatted LastWriteTime length calculation --- .../DefaultFormatters/FileSystem_format_ps1xml.cs | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/FileSystem_format_ps1xml.cs b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/FileSystem_format_ps1xml.cs index 75548e1f61a..4c8d23971af 100644 --- a/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/FileSystem_format_ps1xml.cs +++ b/src/System.Management.Automation/FormatAndOutput/DefaultFormatters/FileSystem_format_ps1xml.cs @@ -49,20 +49,10 @@ private static IEnumerable ViewsOf_FileSystemTypes(CustomC .AddHeader(Alignment.Left, label: "UnixMode", width: 10) .AddHeader(Alignment.Right, label: "User", width: 10) .AddHeader(Alignment.Left, label: "Group", width: 10) - // Until LastWriteTime prints as '{0:d} {0:HH}:{0:mm}', it will always be ShortDatePattern + 6 wide. - // Some locale's ShortDatePattern don't trivially relate to the length of the serialized date string. - // Some patterns only have a single day or month designator but will likely take 2 characters, and - // some even have era designators in their ShortDatePattern, which we take the length of and 1 extra - // for a space character. The Fixed 6 comes from the time suffix, eg. " 23:59". - // https://github.com/PowerShell/PowerShell/issues/19723 .AddHeader( Alignment.Right, label: "LastWriteTime", - width: CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern.Length + - (CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern.AsSpan().Count('d') == 1 ? 1 : 0) + - (CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern.AsSpan().Count('M') == 1 ? 1 : 0) + - (CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern.AsSpan().Count('g') == 1 ? 1 + CultureInfo.CurrentCulture.DateTimeFormat.GetEraName(1).Length : 0) + - 6) + width: String.Format(CultureInfo.CurrentCulture, "{0:d} {0:HH}:{0:mm}", CultureInfo.CurrentCulture.Calendar.MaxSupportedDateTime).Length) .AddHeader(Alignment.Right, label: "Size", width: 12) .AddHeader(Alignment.Left, label: "Name") .StartRowDefinition(wrap: true)