简体   繁体   English

将 DateTime 保存在字符串中并将其解析回来的最佳方法

[英]The best way to save DateTime in string and the parse it back

The code below seems to be ok but it fails when it comes to save/parse Thai calendar, eg 08/31/2555 will fail and will be parsed as 31/8/3108.下面的代码似乎没问题,但在保存/解析泰国日历时失败,例如 08/31/2555 将失败,并将被解析为 31/8/3108。 Why it so?为什么会这样? If I specify "Thai Culture" then it will fail with US/EU time.如果我指定“泰国文化”,那么它将因美国/欧盟时间而失败。

DateTime time = DateTime.Now.AddYears(-10);
String timeString = time.ToString("MM/dd/yyyy HH:mm:ss");

DateTime newTime = DateTime.ParseExact(timeString, "MM/dd/yyyy HH:mm:ss", CultureInfo.InvariantCulture));

Are you sure you get 3108 and not 3098?你确定你得到的是 3108 而不是 3098?

Your string will be in the local calendar (the Thai calendar is 543 years ahead so is 2022 - 10 + 543 = 2555) - then you're reading that date in using the invariant culture (which uses the Gregorian calendar ).您的字符串将在当地日历中(泰历提前 543 年,因此 2022 - 10 + 543 = 2555) - 然后您正在使用不变文化(使用公历)读取该日期。

2555 in the Gregorian calendar is then converted to the Thai calendar when it's being printed, and should result in a second conversion: 2555 + 543 = 3098.公历中的 2555 然后在打印时转换为泰历,并应导致第二次转换:2555 + 543 = 3098。

Your code is equivalent to:您的代码相当于:

const string desiredFormat = "MM/dd/yyyy HH:mm:ss";
Thread.CurrentThread.CurrentCulture = new CultureInfo("th-TH");

// {31/8/2555 15:32:04} - original
var time = DateTime.Now.AddYears(-10);

// "08/31/2555 15:32:04" (Thai calendar string)
var timeStringLocal = time.ToString(desiredFormat);

// {31/8/3098 15:32:04} - incorrect
// 2555 is treated as a Gregorian date, then converted to 3098 in the Thai calendar when displayed
var newTimeFromLocal = DateTime.ParseExact(timeStringLocal, desiredFormat, CultureInfo.InvariantCulture);

What I'd instead suggest that you do is to have the string for parsing use the invariant (Gregorian) calendar instead, which will avoid any such issues.相反,我建议您将用于解析的字符串改为使用不变(公历)日历,这将避免任何此类问题。

const string desiredFormat = "MM/dd/yyyy HH:mm:ss";
Thread.CurrentThread.CurrentCulture = new CultureInfo("th-TH");

// {31/8/2555 15:32:04} - original
var time = DateTime.Now.AddYears(-10);

// "08/31/2012 15:32:04" - (invariant - Gregorian - calendar string)
var timeStringInvariant = time.ToString(desiredFormat, CultureInfo.InvariantCulture);

// {31/8/2555 15:32:04} - correct
var newTimeFromInvariant = DateTime.ParseExact(timeStringInvariant, desiredFormat, CultureInfo.InvariantCulture);

If you have full control over both saving and parsing, you could use a specific culture for both.如果您可以完全控制保存和解析,则可以对两者使用特定的文化

Eg using "en-US" culture:例如使用"en-US"文化:

CultureInfo DATETIME_CULTURE = CultureInfo.GetCultureInfo("en-US");
const string DATETIME_FORMAT = "yyyy/MM/dd_HH:mm:ss";

DateTime time = DateTime.Now.AddYears(-10);
string timeString = time.ToString(DATETIME_FORMAT, DATETIME_CULTURE);
DateTime newTime = DateTime.ParseExact(timeString, DATETIME_FORMAT, DATETIME_CULTURE, DateTimeStyles.None);

Now time should be identical to newTime .现在time应该与newTime相同。

Use a culture-invariant format O :使用文化不变的格式O

var th = new CultureInfo("th-TH");
var us = new CultureInfo("en-US");
var str = DateTime.Now.AddYears(-10).ToString("O");
Console.WriteLine(str);
var dt_th = DateTime.Parse(str, th);
var dt_us = DateTime.Parse(str, us);
Console.WriteLine(dt_th);
Console.WriteLine(dt_us);
Console.WriteLine(dt_th == dt_us);
2012-08-31T14:24:14.4710048+00:00
8/31/2012 2:24:14 PM
8/31/2012 2:24:14 PM
True

If you are saving the string in specific format, then while parsing you have to convert it into the same format first and then parse it to another format.如果要以特定格式保存字符串,则在解析时必须先将其转换为相同的格式,然后再将其解析为另一种格式。 You can refer this answer for help Read date using system locale and convert it to a new format您可以参考此答案以获取帮助Read date using system locale 并将其转换为新格式

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM