DateTime.ToString("yyyy.MM.dd-HH_mm_ss") 仅在某些日本笔记本电脑上导致不正确的 'year' 组件

DateTime.ToString("yyyy.MM.dd-HH_mm_ss") resulted in incorrect 'year' component only on certain Japanese laptops

我们有一个 WPF 应用程序,全世界的用户都在使用它。 我们在代码中有以下日期对话。

DateTime dt = <some date time value>;

var formattedDateTime = (dt.ToString("yyyy.MM.dd-HH_mm_ss"));

此行在一些具有日本文化集的日本笔记本电脑中给出了不正确的结果。

例如dt值为{2019/09/11 14:42:47}:

我认为这些笔记本电脑上的一些日本文化设置导致了这个问题。但我无法弄清楚那个设置是什么。 此外,我认为将 CultureInfo.InvariantCulture 添加到 DateTime.ToString() 可能会解决此问题。

知道是什么设置导致了这个问题吗?

const string culture = "ja-JP";
CultureInfo info = new CultureInfo(culture);
var formattedDateTime = (dt.ToString("yyyy.MM.dd-HH_mm_ss" , info));

您的一些用户将他们的 Windows 日期格式设置为使用日本日历,其中 2019 年是令和纪元的第一年。他们可以通过进入 Windows 控制面板并将日期格式更改为显示公历年份的选项之一(“ggy”而不是“y”)来解决您的问题,或者更改他们的从日文到公历的日历类型。

据您所说,在某些机器上,日本文化默认使用 Japanese calendar rather than the Gregorian calendar

日本日历使用基于天皇在位的纪元,例如:

  • 昭和 (昭和) 从 1926/12/25 - 1989/01/07
  • Heisei (平成) 从 1989/01/08 - 2019/04/30
  • 令和 (令和) 从 2019/05/01 到现在

我们可以在代码中进行测试:

var jpCulture = new CultureInfo("ja-jp");
jpCulture.DateTimeFormat.Calendar = new JapaneseCalendar();
// output: 昭和 63/05/11
Console.WriteLine(new DateTime(1988, 05, 11).ToString("g yyyy/MM/dd", jpCulture));
// output: 平成 20/05/11
Console.WriteLine(new DateTime(2008, 05, 11).ToString("g yyyy/MM/dd", jpCulture));
// output: 平成 31/04/30
Console.WriteLine(new DateTime(2019, 04, 30).ToString("g yyyy/MM/dd", jpCulture));
// output: 令和 01/05/01
Console.WriteLine(new DateTime(2019, 05, 01).ToString("g yyyy/MM/dd", jpCulture));

您的选择是:

  1. 按照 Robyn 的建议,让用户将他们的 OS 日历设置更改为公历(用户的当前设置将是和暦 - 日本日历 - 需要更改为西暦 - 西方日历)。

  1. 使用不变区域性显式格式化日期:
string myDateString = DateTime.Now.ToString("yyyy/MM/dd", CultureInfo.InvariantCulture);
  1. 在启动时,强制使用公历的文化。 请注意,使用此选项后,其他代码可以在稍后执行程序时自由更改“当前”区域性。
CultureInfo ci = (CultureInfo)CultureInfo.CurrentCulture.Clone();
ci.DateTimeFormat.Calendar = new GregorianCalendar();
CultureInfo.CurrentCulture = ci;
CultureInfo.CurrentUICulture = ci;
  1. 创建一个包装器方法来包装 ToString 功能并在当前日历不是公历时添加纪元:
public static class DateTimeExtensions
{
    public static string ToStringYMDWithEra(this DateTime dt)
    {
        string formatString = (CultureInfo.CurrentCulture.Calendar is GregorianCalendar) 
            ? "yyyy/MM/dd"
            : "gyyyy/MM/dd";
        return dt.ToString(formatString);           
    }
}

用法:string formattedDate = DateTime.Now.ToStringYMDWithEra();

请注意,日本用户会隐含地理解带有纪元的日本日历。从表格到医生登记,再到任何官方信息,一切都使用日本日历系统。例如,我的驾照上有我出生年份(1988)的昭和63。