C# 以多种格式解析日期时间
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17859421/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Parse datetime in multiple formats
提问by Vivek Jain
I have created an API end-point. The caller may call the API with POSTmethod passing the relevant parameters. In the parameters there is one parameter that is of datetimeformat.
我已经创建了一个 API 端点。调用者可以POST通过传递相关参数的方法调用API 。在参数中有一个参数是datetime格式。
The problem is that when calling this API the caller may passes datetimein 3 different formats:
问题是当调用这个 API 时,调用者可能会传入datetime3 种不同的格式:
long int- e.g. 1374755180- US format - e.g. "7/25/2013 6:37:31 PM" (as
string) - Timestamp format - e.g. "2013-07-25 14:26:00" (as
string)
long int- 例如 1374755180- 美国格式 - 例如“7/25/2013 6:37:31 PM”(作为
string) - 时间戳格式 - 例如“2013-07-25 14:26:00”(如
string)
I have to parse the datetimevalue and convert it to a DateTimeor stringin Timestamp format.
我必须解析该datetime值并将其转换为时间戳格式的DateTime或string。
I have tried using DateTime.TryParse(), DateTime.Parse(), Convert.ToDateTime()and Convert.ToDouble()but none of them are working in certainty for me.
我已经尝试使用DateTime.TryParse(),DateTime.Parse(),Convert.ToDateTime()和Convert.ToDouble(),但他们都不在肯定为我工作。
The required output has to be in en-GBformat.
所需的输出必须符合en-GB格式。
Edit:
编辑:
I had thought to have an if-else if-elseblock to use with TryParse3 times with one elseto say the string could not be parsed. Is this the best solution? Or are there solutions better than this?
我曾想有一个if-else if-else块可以使用TryParse3 次,其中一个else表示无法解析字符串。这是最好的解决方案吗?或者有比这更好的解决方案吗?
Please help!
请帮忙!
采纳答案by Randy James
You should consider requiring a timezone. 1 doesn't need it, but #2 and #3 do.
您应该考虑要求时区。1 不需要它,但 #2 和 #3 需要。
public DateTime ParseRequestDate()
{
// https://stackoverflow.com/questions/2883576/how-do-you-convert-epoch-time-in-c
CultureInfo enUS = new CultureInfo("en-US");
var dt = "1374755180";
//var dt = "7/25/2013 6:37:31 PM";
//var dt = "2013-07-25 14:26:00";
DateTime dateValue;
long dtLong;
// Scenario #1
if (long.TryParse(dt, out dtLong))
return dtLong.FromUnixTime();
// Scenario #2
if (DateTime.TryParseExact(dt, "MM/dd/yyyy hh:mm:ss tt", enUS, DateTimeStyles.None, out dateValue))
return dateValue;
// Scenario #3
if (DateTime.TryParseExact(dt, "yyyy-MM-dd hh:mm:ss", enUS, DateTimeStyles.None, out dateValue))
return dateValue;
throw new SomeException("Don't know how to parse...");
}
EDITAs Matt Johnson points out, DateTime.TryParseExact accepts an array of format strings. 2 & 3 could be condensed.
编辑正如马特约翰逊指出的那样, DateTime.TryParseExact 接受格式字符串数组。2 & 3 可以压缩。
public DateTime ParseRequestDate()
{
// https://stackoverflow.com/questions/2883576/how-do-you-convert-epoch-time-in-c
CultureInfo enUS = new CultureInfo("en-US");
var dt = "1374755180";
//var dt = "7/25/2013 6:37:31 PM";
//var dt = "2013-07-25 14:26:00";
DateTime dateValue;
long dtLong;
// Scenario #1
if (long.TryParse(dt, out dtLong))
return dtLong.FromUnixTime();
// Scenario #2 & #3
var formatStrings = new string[] { "MM/dd/yyyy hh:mm:ss tt", "yyyy-MM-dd hh:mm:ss" };
if (DateTime.TryParseExact(dt, formatStrings, enUS, DateTimeStyles.None, out dateValue))
return dateValue;
throw new SomeException("Don't know how to parse...");
}
The epoch conversion I borrowed from another question.(An extension method)
我从另一个问题借来的时代转换。(一种扩展方法)
public static class MyExtensions
{
public static DateTime FromUnixTime(this long unixTime)
{
var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
return epoch.AddSeconds(unixTime);
}
}
回答by Shekhar_Pro
If the possible formats are fixed then you can use TryParseExact
如果可能的格式是固定的,那么您可以使用TryParseExact
A possible solution is to use TryParse, if it fails to get proper date then fallback to known formats and use TryPraseExact
一个可能的解决方案是使用TryParse,如果它无法获得正确的日期,则回退到已知格式并使用TryPraseExact
回答by dasblinkenlight
One way to deal with this problem would be setting up a factory method that "understands" different formats, and parses them accordingly.
处理这个问题的一种方法是设置一个“理解”不同格式的工厂方法,并相应地解析它们。
You can create a chain of if-then-elses to deal with this problem, but you can also make a "table-driven" implementation: what you need is an array of delegates that take a string, and tell you two things:
您可以创建一个if- then-链else来处理这个问题,但您也可以进行“表驱动”实现:您需要的是一个接受字符串的委托数组,并告诉您两件事:
- Whether or not this delegate can parse the incoming string, and
- If yes, what is the result of that parse, expressed as
DateTime
- 此委托是否可以解析传入的字符串,以及
- 如果是,那么解析的结果是什么,表示为
DateTime
Here is a sample implementation:
这是一个示例实现:
private static readonly DateParsers = new Func<string,Tuple<DateTime,bool>>[] {
(s) => {
long res;
if (long.TryParse(s, out res)) {
// The format was correct - make a DateTime,
// and return true to indicate a successful parse
return Tuple.Create(new DateTime(res), true);
} else {
// It does not matter what you put in the Item1
// when Item2 of the tuple is set to false
return Tuple.Create(DateTime.MinValue, false);
}
}
...
// Add similar delegates for other formats here
};
Now your factory method could be implemented as follows:
现在你的工厂方法可以实现如下:
private static bool TryParseMultiformat(string s, out DateTime res) {
// Check all parsers in turn, looking for one returning success
foreach (var p in DateParsers) {
var tmp = p(s);
if (tmp.Item2) {
res = tmp.Item1;
return true;
}
}
res = DateTime.MinValue;
return false;
}
回答by Darbio
You are looking for the DateTime.ParseExact(MSDN Article)
您正在寻找DateTime.ParseExact(MSDN 文章)
Which you would use in a situation like this:
你会在这样的情况下使用它:
string[] formats= { "MM/dd/yyyy hh:mm:ss tt", "yyyy-MM-dd hh:mm:ss" }
var dateTime = DateTime.ParseExact("7/25/2013 6:37:31 PM", formats, new CultureInfo("en-GB"), DateTimeStyles.None);
This allows you to add as many DateTimeformats to the arrayas you need and the method will do the conversion without the if...elsestatements.
这允许您根据需要向 中添加任意数量的DateTime格式,array并且该方法将在没有if...else语句的情况下进行转换。
If your integer is in seconds since Unix Epochyou add the number of seconds to the DateTime of the Epoch (01/01/1970) (.Net doesn't have an out of the box method for this, but the logic is seconds since 'Epoch'):
如果您的整数是自Unix Epoch以来的秒数,您将秒数添加到 Epoch (01/01/1970) 的 DateTime(.Net 没有开箱即用的方法,但逻辑是自'时代'):
new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(seconds);
From this question.
从这个问题。
回答by Vivek Jain
Thanks for your answers. I tried the options suggested in couple of answers and found out a very simple approach that worked for me.
感谢您的回答。我尝试了几个答案中建议的选项,并找到了一种对我有用的非常简单的方法。
public static bool ParseDate(string dateString, out DateTime dateValue)
{
long dtLong = 0L;
bool result = false;
if (long.TryParse(dateString, out dtLong))
{
// I copied the epoch code here for simplicity
dateValue = new DateTime(1970, 1, 1, 0, 0, 0).AddSeconds(dtLong);
result = true;
}
// Working for US and Timestamp formats
else if (DateTime.TryParse(dateString, out dateValue))
result = true;
return result;
}
Earlier I was trying to use TryParsefor all the 3 formats which was not working.
早些时候,我试图将TryParse所有 3 种格式都使用,但这些格式都不起作用。
Somehow, TryParseExactdid not work for the timestamp format. It worked for the US format. That is the reason I had to write my own.
不知何故,TryParseExact不适用于时间戳格式。它适用于美国格式。这就是我必须自己写的原因。
回答by Juan Ayala
If you use TryParseExact, only G-O-D and the Microsoft developers know how many possible date time formats it will try to parse before it gives up. Perhaps a better solution is to use a quick regex and then an appropriate parser. I tried to make the regex as simple as possibke, you may have to tweak this a little
如果您使用TryParseExact,则只有 GOD 和 Microsoft 开发人员知道它会在放弃之前尝试解析多少种可能的日期时间格式。也许更好的解决方案是使用快速正则表达式,然后使用适当的解析器。我试图让正则表达式像 possibke 一样简单,你可能需要稍微调整一下
private static readonly Regex R1
= new Regex(@"^\d+$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline);
private static readonly Regex R2
= new Regex(@"M$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline);
private static readonly Regex R3
= new Regex(@"^\d{4}-", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline);
private static void Main(string[] args)
{
string[] stringDates = new[]
{
"1374755180",
"2013-07-25 14:26:00",
"7/25/2013 6:37:31 PM"
};
foreach (var s in stringDates)
{
DateTime date = default(DateTime);
if (R1.IsMatch(s))
date = new DateTime(long.Parse(s));
else if (R2.IsMatch(s))
date = DateTime.Parse(s);
else if (R3.IsMatch(s))
date = DateTime.Parse(s);
if (date != default(DateTime))
Console.WriteLine("{0}", date);
}
Console.WriteLine("Press ENTER to continue...");
Console.ReadLine();
}
回答by Korayem
I was facing same problem in a project where my code will run on different environments with various culture formats.
我在一个项目中遇到了同样的问题,我的代码将在具有各种文化格式的不同环境中运行。
Google showed me this hidden gem. The helper function is indispensable to auto-parse datetime properly regardless of culture formats
谷歌向我展示了这个隐藏的宝石。无论文化格式如何,辅助函数对于正确自动解析日期时间都是必不可少的
Usage Examples:
用法示例:
string str = @"The last round was June 10, 2005; this time the unbroken record was held.";
DateTimeRoutines.ParsedDateTime pdt;
if (DateTimeRoutines.TryParseDate(str, DateTimeRoutines.DateTimeFormat.USA_DATE, out pdt))
Console.WriteLine("Date was found: " + pdt.DateTime.ToString());
According to the author, the code is capable of parsing various cases:
根据作者的说法,该代码能够解析各种情况:
@"Member since: 10-Feb-2008"
@"Last Update: 18:16 11 Feb '08 "
@"date Tue, Feb 10, 2008 at 11:06 AM"
@"see at 12/31/2007 14:16:32"
@"sack finish 14:16:32 November 15 2008, 1-144 app"
@"Genesis Message - Wed 04 Feb 08 - 19:40"
@"The day 07/31/07 14:16:32 is "
@"Shipping is on us until December 24, 2008 within the U.S."
@" 2008 within the U.S. at 14:16:32"
@"5th November, 1994, 8:15:30 pm"
@"7 boxes January 31 , 14:16:32."
@"the blue sky of Sept 30th 2008 14:16:32"
@" e.g. 1997-07-16T19:20:30+01:00"
@"Apr 1st, 2008 14:16:32 tufa 6767"
@"wait for 07/31/07 14:16:32"
@"later 12.31.08 and before 1.01.09"
@"Expires: Sept 30th 2008 14:16:32"
@"Offer expires Apr 1st, 2007, 14:16:32"
@"Expires 14:16:32 January 31."
@"Expires 14:16:32 January 31-st."
@"Expires 23rd January 2010."
@"Expires January 22nd, 2010."
@"Expires DEC 22, 2010."

