以文化中性格式存储日期时间+ C#

时间:2014-11-18 11:41:11

标签: c# .net date datetime datepicker

我通过日期选择器接受来自用户的日期信息。我需要以文化中立的方式存储它们。我面临的问题是,如果我按照en-US格式存储日期(基于日历设置),即11/20/1990,当文化为en-GB时,它将无法解析。

反之亦然,当文化为en-US时,日期按英国格式存储,dd / mm / yyyy拒绝解析。如何以文化中立的方式在文件中存储日期信息,以便我在两个位置都可以使用日期?

DateTime.TryParse(userEnteredValue, out result);
result.ToShortDateString(); //this is what I am doing 

尝试使用此代码进行不变文化

string input = "20/10/1983";
DateTime userInput;

bool result = DateTime.TryParse(input, out userInput);

string invariantCulture = userInput.Date.ToString(CultureInfo.InvariantCulture);

DateTime storedValue;

result = DateTime.TryParse(invariantCulture, out storedValue);

使用en-GB日历设置尝试此代码,第二个语句DateTime.TryParse失败。

7 个答案:

答案 0 :(得分:4)

@SonerGönül的回答是如果您将日期保存到数据库的话。但是,您提到要将DateTime往返于文件进行往返。

由于文件可能是文本文件,因此您需要以文化中立的方式编写DateTime。您可以使用DateTime.ToString方法中指定的"O" format执行此操作。这将输出符合ISO 8601的字符串表示。可以使用DateTime.Parse解析结果字符串,而无需文化信息。

举个例子:

string filename = @"c:\temp\test.txt";
string usDateString = "11/18/2014 12:32"; // MM/dd/yyyy
string ukDateString = "18/11/2014 12:33"; // dd/MM/yyyy

//I'm mimicking you getting the DateTime from the user here    
//I'm assuming when you receive the date(s) from the front
//end you'll know the culture - if not then all bets are off. 
DateTime usDate = 
      DateTime.Parse(usDateString, CultureInfo.GetCultureInfo("en-US"));
DateTime ukDate = 
      DateTime.Parse(ukDateString, CultureInfo.GetCultureInfo("en-GB"));

//write the dates to a file using the "o" specifier
File.AppendAllText(filename, usDate.ToString("o") + Environment.NewLine);
File.AppendAllText(filename, ukDate.ToString("o") + Environment.NewLine);

//read them back in as strings
string[] contents = File.ReadAllLines(filename);

foreach (var date in contents)
{
    //prove we can parse them as dates.
    Console.WriteLine(DateTime.Parse(date).ToString());
}

这会创建一个包含以下内容的文件:

  

2014-11-18T12:32:00.0000000

     

2014-11-18T12:33:00.0000000

并在我的系统(在英国)打印:

  

18/11/2014 12:32:00

     

18/11/2014 12:33:00

答案 1 :(得分:3)

  

如果我按照en-US格式存储日期......

请停止!您似乎尝试使用字符串表示法保存DateTime值。

DateTime没有任何隐式格式。它只有日期和时间值。它们的字符串表示可以具有格式。生成您的插入查询,并使用parameterized way直接传递您的DateTime

请阅读;

如果您希望使用特定格式获取DateTime值的字符串表示形式,则可以始终使用DateTime.ToString()方法及其重载。

您的en-GB文化可以解析MM.dd.yyyy(因为您使用/ format specifier替换了自己提供的文化DateSeparator)和en-US文化可以解析MM/dd/yyyy也是。

但是,由于您使用.ToShortDateString()方法,因此根据您的CurrentCulture设置表示您的日期时间。作为解决方案,您可以将此属性设置为您想要的文化,ToShortDateString可以根据它进行工作。


result = DateTime.TryParse(invariantCulture, out storedValue);
     

使用en-UK日历设置尝试此代码,第二个声明   DateTime.TryParse失败了。

由于此DateTime.TryParse使用了您的CurrentCulture而且invariantCulture变量为10/20/1983 00:00:00,因此这不是CurrentCulture的标准日期和时间格式}。

顺便说一下,en-UK没有这样的文化。


10/20/1983 00:00:00格式为MM/dd/yyyy HH:mm:ss。但en-GB文化并未将此格式设为标准日期和时间格式,这就是您的方法返回false的原因。

作为替代方案,您可以使用自定义格式字符串,如;

string s = "10/20/1983 00:00:00";
string format = "MM/dd/yyyy HH:mm:ss";
DateTime dt;
if (DateTime.TryParseExact(s, format, CultureInfo.GetCultureInfo("en-GB"),
                           DateTimeStyles.None, out dt))
{
    Console.WriteLine(dt);
}

答案 2 :(得分:1)

我碰到了这个问题,并且发现我还带来了其他人没有提到的其他方式:

DateTime.ToBinary()用于序列化,DateTime.FromBinary(Int64)用于反序列化。

以下是这些: ToBinary()返回一个long,可以很容易地以文化不变的方式存储。 FromBinary(Int64)将从提供的long参数返回DateTime对象。 (他们甚至考虑日期时间Kind属性。)

这里有一些代码:

DateTime d1l = DateTime.Now;
long dl = d1l.ToBinary();
DateTime d2l = DateTime.FromBinary(dl);

DateTime d1u = DateTime.UtcNow;
long du = d1u.ToBinary();
DateTime d2u = DateTime.FromBinary(du);

Console.WriteLine("Local test passed: " + (d1l == d2l).ToString());
Console.WriteLine("d2l kind: " + d2l.Kind.ToString());
Console.WriteLine("Utc test passed: " + (d1u == d2u).ToString());
Console.WriteLine("d2u kind: " + d2u.Kind.ToString());

控制台输出:

Local test passed: True
d2l kind: Local
Utc test passed: True
d2u kind: Utc

我觉得这很漂亮!

答案 3 :(得分:0)

String s = "24. 11. 2001";
d = DateTime.Parse(s, CultureInfo.CreateSpecificCulture("sk-SK"));
  1. en-AU(English Austrailia):24/11/2001
  2. en-IA(英文印度):24-11-2001
  3. en-ZA(英语南非):2001/11/24
  4. en-US(美国英语):11/24/2001
  5. 我怀疑你更喜欢英语(印度)(en-IA)。

    但是如果你真的无法决定在将日期转换为字符串时使用什么文化,反之亦然,并且日期永远不会向用户显示,那么你可以使用不变文化:

    String s = "11/24/2001" //invariant culture formatted date
    
    d = DateTime.Parse(s, CultureInfo.InvariantCulture); //parse invariant culture date
    
    s = d.ToString(CultureInfo.InvariantCulture); //convert to invariant culture string
    

答案 4 :(得分:0)

我试图通过这种方法找出解决方案,请告诉我它是否正确。

我使用的代码如下。

对于保存日期时间,我使用以下滴答。

DateTime userInput;

bool result = DateTime.TryParse(this.dpSave.Text, out userInput);

if (result)
{
   long ticks = userInput.Ticks;

   System.IO.File.WriteAllText(@"D:\folder\Ticks.txt", ticks.ToString());
 }
 else
 {
   MessageBox.Show("Date time parse failed");
 }

为了加载它,我使用

if (System.IO.File.Exists(@"D:\folder\Ticks.txt"))
{
   string contents = System.IO.File.ReadAllText(@"D:\Sandeep\Ticks.txt");

   long ticks;

   if (long.TryParse(contents, out ticks))
   {
     DateTime storedDateTime = new DateTime(ticks);
     MessageBox.Show("Stored Date" + storedDateTime.ToShortDateString());
   }
   else
   {
     MessageBox.Show("Unable to obtain stored dates");
   }
}

这似乎有用,只要我使用en-US文化保存并使用en-GB文化加载。

如果这是正确的方法,请告诉我!

答案 5 :(得分:0)

a)交换数据应始终存储文化不变(xml等)

b)你必须小心这个术语。 你究竟指的是文化INVARIANT(而不是'文化中立')。 有三种文化类型: 1)不变量 2)文化中立(例如" en") 3)特定文化(例如" en-US")

答案 6 :(得分:0)

public DateTime getdate3()
{

    CultureInfo Invc = CultureInfo.InvariantCulture;    //culture
    string cul = Thread.CurrentThread.CurrentCulture.Name;

    CultureInfo us = new CultureInfo(cul);
    string shortUsDateFormatString = us.DateTimeFormat.ShortDatePattern;//pattern


    DateTime dt = Convert.ToDateTime(DateTime.Now);

    TimeZoneInfo myZone = TimeZoneInfo.FindSystemTimeZoneById("India Standard Time"); //india zone
    DateTime dateindia = TimeZoneInfo.ConvertTime(dt, myZone);

    string dt1 = Convert.ToDateTime(dateindia).ToString(shortUsDateFormatString); //string format

}