代码之家  ›  专栏  ›  技术社区  ›  Richard Slater

为什么datetime.toshortTimeString()不遵守“区域和语言设置”中的短时间格式?

  •  10
  • Richard Slater  · 技术社区  · 16 年前

    我遇到了一个问题,可能是因为我对datetime.toshortTimeString()方法的工作方式理解错误。当用这个函数格式化时间字符串时,我假设它将尊重Windows7的格式设置中的“短时间”设置。

    Control Panel -> Clock, Language and Region -> Region and Language -> Formats Tab.

    但是.NET似乎选择了一种短时间格式,而不是基于此设置,而是基于当前区域性:

    Region and Language -> Location -> Current Location

    我在Windows7RC上做了一些测试:

    Culture: en-GB, 6AM: 06:00, 6PM: 18:00 // HH:mm (United Kingdom)
    Culture: en-GB, 6AM: 06:00, 6PM: 18:00 // hh:mm (United Kingdom)
    Culture: en-US, 6AM: 6:00 AM, 6PM: 6:00 PM // HH:mm (United States)
    Culture: en-US, 6AM: 6:00 AM, 6PM: 6:00 PM // hh:mm (United States)
    Culture: el-GR, 6AM: 6:00 πμ, 6PM: 6:00 μμ // HH:mm (Greece)
    Culture: el-GR, 6AM: 6:00 πμ, 6PM: 6:00 μμ // hh:mm (Greece)
    

    我使用了el gr,因为这是用户报告问题的文化,他还在vista sp2上测试了这个问题,并用相同的结果赢得了7个rc。

    问题有两个方面: 1)我对.NET和Windows格式有什么误解? 2)基于操作系统创建短格式时间字符串(hh:mm或hh:mm tt)的最佳解决方案是什么,理想情况下这应该在mono中工作,因此我希望避免从注册表或P/Invoke中读取。

    用于生成上述内容的方法,以供将来参考和测试。

    [STAThread]
    static void Main(string[] args)
    {
        CultureInfo culture = CultureInfo.CurrentCulture;
    
        DateTime sixAm = new DateTime(2009, 07, 05, 6, 0, 0); // 6AM 
        DateTime sixPm = new DateTime(2009, 07, 05, 18, 0, 0); // 6PM
    
        string sixAmString = sixAm.ToShortTimeString();
        string sixPmString = sixPm.ToShortTimeString();
    
        string format = "Culture: {0}, 6AM: {1}, 6PM: {2}";
    
        string output = String.Format(format, culture, sixAmString, sixPmString);
        Console.WriteLine(output);
        Clipboard.Clear();
        Clipboard.SetText(output);
    
        Console.ReadKey();
    }
    

    更新: 根据Mike下面的评论,我对上述方法进行了如下修改:

    下面两行

    string sixAmString = sixAm.ToShortTimeString();
    string sixPmString = sixPm.ToShortTimeString();
    

    改为

    string sixAmString = sixAm.ToString("t", culture);
    string sixPmString = sixPm.ToString("t", culture);
    

    我还将culture变量更改为使用cultureinfo.currentuiculture。

    不幸的是,这并不像我希望的那样有效,不管Windows7的“格式”选项卡中短时间的配置如何,输出都是:

    Culture: en-US, 6AM: 6:00 AM, 6PM: 6:00 PM
    

    现在的文化似乎总是存在于我们身上。

    3 回复  |  直到 12 年前
        1
  •  5
  •   Reinderien    12 年前

    第二个问题的答案是

    DateTimeFormat.Format(DateTime.Now, "t", CultureInfo.CurrentUICulture);
    

    DateTime.Now.ToString("t", CultureInfo.CurrentUICulture);
    

    实际上,最好使用接受CultureInfo的显式方法。在默认情况下,.NET如何选择要使用的内容没有一致性:currentCulture、currentUICulture或invarianatCulture。

    使答案完整。此外,我还将概述不同文化之间的差异。

    因此,当前区域性是“控制面板->时钟、语言和区域->区域和语言->格式选项卡”。这是您希望计算的区域性。例如,您可以在美国进行会计核算,因此您需要在美国进行配置。

    当前的uiculture是“地区和语言-显示语言”,意味着当您从乌克兰移民时,您希望您的应用程序在UA中本地化(但所有计算仍在美国)。

    而不变文化就是所谓的文化不可知论的地方。您应该使用它来存储信息等等。事实上,这就是我们。

    注意:每个设置在Windows中的位置可能是错误的。但你可能有个主意。

        2
  •  2
  •   Zaz    13 年前

    我很确定,在datetime.toshortTimeString()或datetime.toString(“t”)中没有使用短时间格式字符串这一事实是一个错误,因为它是在.NET Framework 4.0中修复的。

        3
  •  1
  •   Richard Slater    16 年前

    回答我的每个问题:

    1)我对.NET和Windows格式有什么误解?

    简言之,“区域和语言”设置中的“短时间”设置与.NET的shorttimepattern属性之间没有链接。但是,long time模式属性由“long time”设置决定。

    我将上面的方法替换为两个格式化行:

    string sixAmString = sixAm.ToString("T", culture.DateTimeFormat);
    string sixPmString = sixPm.ToString("T", culture.DateTimeFormat);
    

    以下是输出:

    Culture: en-GB, 6AM: 06:00:00, 6PM: 18:00:00 // HH:mm:ss
    Culture: en-GB, 6AM: 06:00:00 AM, 6PM: 06:00:00 PM //hh:mm:ss tt
    

    底部 this article 向我解释了这个问题。

    2)根据操作系统设置创建短格式时间字符串(hh:mm或hh:mm tt)的最佳解决方案是什么?

    我不知道最佳解决方案,但我创建了以下函数,将longtimeformat转换为shorttimeformat,从而允许应用程序在更改“long time”(长时间)时遵循用户选项(尽管它不会跟踪“short time”(短时间)设置)。

    static string GetShortTimeString(DateTime ShortTimeString)
    {
        DateTimeFormatInfo dateTimeFormat = CultureInfo.CurrentCulture.DateTimeFormat;
        string ShortTimePattern = dateTimeFormat.LongTimePattern.Replace(":ss", String.Empty);
        ShortTimePattern = ShortTimePattern.Replace(":s", String.Empty);
    
        return ShortTimeString.ToString(ShortTimePattern);
    }
    

    进行上述更改后的输出:

    Culture: en-GB, 6AM: 06:00, 6PM: 18:00
    Culture: en-GB, 6AM: 06:00 AM, 6PM: 06:00 PM
    

    p/invoke选项是使用 GetTimeFormat 使用上面的datetime.toString(格式)传递时间秒。我还没有测试这个,因为我希望避免使用p/invoke。