Programming

C #에서 문자열을 DateTime으로 구문 분석

procodes 2020. 6. 7. 17:22
반응형

C #에서 문자열을 DateTime으로 구문 분석


다음 과 같은 형식의 문자열에 날짜와 시간있습니다 .

"2011-03-21 13:26" //year-month-day hour:minute

어떻게 파싱 할 수 System.DateTime있습니까?

날짜 형식을 수동으로 지정할 수 있도록 DateTime.Parse()또는 DateTime.ParseExact()가능한 경우 와 같은 기능을 사용하고 싶습니다 .


DateTime.Parse()주어진 날짜의 형식을 알아 내려고 시도하면 일반적으로 잘 작동합니다. 날짜가 항상 주어진 형식으로 보장 될 수 있다면 다음을 사용할 수 있습니다 ParseExact().

string s = "2011-03-21 13:26";

DateTime dt = 
    DateTime.ParseExact(s, "yyyy-MM-dd HH:mm", CultureInfo.InvariantCulture);

(하지만 날짜가 예상 형식이 아닌 경우 일반적으로 TryParse 메서드 중 하나를 사용하는 것이 더 안전합니다)

형식 문자열 을 구성 할 때 사용자 정의 날짜 및 시간 형식 문자열 을 확인하십시오 . 특히 문자 수와 대소 문자에주의하십시오 (예 : "MM"과 "mm"은 매우 다른 의미).

C # 형식 문자열에 유용한 또 다른 리소스는 C #의 문자열 형식입니다.


나중에 설명 할 때 항상 TryParseand TryParseExact메소드를 선호합니다 . 그것들은 사용하기에 부피가 크므로 구문 분석을 훨씬 쉽게 하는 확장 방법작성했습니다 .

var    dtStr = "2011-03-21 13:26";
DateTime? dt = dtStr.ToDate("yyyy-MM-dd HH:mm");

달리 Parse, ParseExact등은 예외를 던져, 당신은을 통해 확인할 수 있습니다하지 않습니다

if (dt.HasValue) { // continue processing } else { // do error handling }

변환 (이 경우 성공 여부를 dt당신이를 통해 액세스 할 수있는 값을 가지고 dt.Value) 또는하지 (이 경우,이다 null).

"Elvis"-operator와 같은 고급 바로 가기를 사용할 수도 있습니다 ?..

int? year = dtStr?.ToDate("yyyy-MM-dd HH:mm")?.Year;

여기 year.HasValue에서 전환이 성공했는지 여부를 확인하고 성공하지 못한 경우 year에는을 포함 null하고 그렇지 않은 경우 날짜의 연도 부분을 포함 할 수도 있습니다. 변환에 실패한 경우 예외가 발생하지 않습니다.


솔루션 :   .ToDate () 확장 메소드

.NetFiddle에서 사용해보십시오

public static class Extensions
{
    // Extension method parsing a date string to a DateTime?
    // dateFmt is optional and allows to pass a parsing pattern array
    // or one or more patterns passed as string parameters
    public static DateTime? ToDate(this string dateTimeStr, params string[] dateFmt)
    {
      // example: var dt = "2011-03-21 13:26".ToDate(new string[]{"yyyy-MM-dd HH:mm", 
      //                                                  "M/d/yyyy h:mm:ss tt"});
      // or simpler: 
      // var dt = "2011-03-21 13:26".ToDate("yyyy-MM-dd HH:mm", "M/d/yyyy h:mm:ss tt");
      const DateTimeStyles style = DateTimeStyles.AllowWhiteSpaces;
      if (dateFmt == null)
      {
        var dateInfo = System.Threading.Thread.CurrentThread.CurrentCulture.DateTimeFormat;
        dateFmt=dateInfo.GetAllDateTimePatterns();
      }
      // Commented out below because it can be done shorter as shown below.
      // For older C# versions (older than C#7) you need it like that:
      // DateTime? result = null;
      // DateTime dt;
      // if (DateTime.TryParseExact(dateTimeStr, dateFmt,
      //    CultureInfo.InvariantCulture, style, out dt)) result = dt;
      // In C#7 and above, we can simply write:
      var result = DateTime.TryParseExact(dateTimeStr, dateFmt, CultureInfo.InvariantCulture,
                   style, out var dt) ? dt : null as DateTime?;
      return result;
    }
}

코드에 대한 일부 정보

InvariantCulture호출 을 사용했는지 궁금 할 것입니다 TryParseExact: 이것은 형식 패턴을 항상 같은 방식으로 처리하도록 강제하는 것입니다 (예 : "."는 그룹 구분 기호 또는 날짜 구분 기호 인 동안 영어로 소수점 구분 기호로 해석 될 수 있음) 독일 사람). 문화 기반 형식 문자열을 몇 줄 전에 이미 쿼리 했으므로 여기서는 괜찮습니다.

Update: .ToDate() (without parameters) now defaults to all common date/time patterns of the thread's current culture.
Note that we need the result and dt together, because TryParseExact does not allow to use DateTime?, which we intend to return. In C# Version 7 you could simplify the ToDate function a bit as follows:

 // in C#7 only: "DateTime dt;" - no longer required, declare implicitly
 if (DateTime.TryParseExact(dateTimeStr, dateFmt,
     CultureInfo.InvariantCulture, style, out var dt)) result = dt;

or, if you like it even shorter:

 // in C#7 only: Declaration of result as a "one-liner" ;-)
 var result = DateTime.TryParseExact(dateTimeStr, dateFmt, CultureInfo.InvariantCulture,
              style, out var dt) ? dt : null as DateTime?;

in which case you don't need the two declarations DateTime? result = null; and DateTime dt; at all - you can do it in one line of code. (It would also be allowed to write out DateTime dt instead of out var dt if you prefer that).

I have simplified the code further by using the params keyword: Now you don't need the 2nd overloaded method any more.


Example of usage

var dtStr="2011-03-21 13:26";    
var dt=dtStr.ToDate("yyyy-MM-dd HH:mm");
if (dt.HasValue)
{
    Console.WriteLine("Successful!");
    // ... dt.Value now contains the converted DateTime ...
}
else
{
    Console.WriteLine("Invalid date format!");
}

As you can see, this example just queries dt.HasValue to see if the conversion was successful or not. As an extra bonus, TryParseExact allows to specify strict DateTimeStyles so you know exactly whether a proper date/time string has been passed or not.


More Examples of usage

The overloaded function allows you to pass an array of valid formats used for parsing/converting dates as shown here as well (TryParseExact directly supports this), e.g.

string[] dateFmt = {"M/d/yyyy h:mm:ss tt", "M/d/yyyy h:mm tt", 
                     "MM/dd/yyyy hh:mm:ss", "M/d/yyyy h:mm:ss", 
                     "M/d/yyyy hh:mm tt", "M/d/yyyy hh tt", 
                     "M/d/yyyy h:mm", "M/d/yyyy h:mm", 
                     "MM/dd/yyyy hh:mm", "M/dd/yyyy hh:mm"};
var dtStr="5/1/2009 6:32 PM"; 
var dt=dtStr.ToDate(dateFmt);

If you have only a few template patterns, you can also write:

var dateStr = "2011-03-21 13:26";
var dt = dateStr.ToDate("yyyy-MM-dd HH:mm", "M/d/yyyy h:mm:ss tt");

Advanced examples

You can use the ?? operator to default to a fail-safe format, e.g.

var dtStr = "2017-12-30 11:37:00";
var dt = (dtStr.ToDate()) ?? dtStr.ToDate("yyyy-MM-dd HH:mm:ss");

In this case, the .ToDate() would use common local culture date formats, and if all these failed, it would try to use the ISO standard format "yyyy-MM-dd HH:mm:ss" as a fallback. This way, the extension function allows to "chain" different fallback formats easily.

You can even use the extension in LINQ, try this out (it's in the .NetFiddle above):

var patterns=new[] { "dd-MM-yyyy", "dd.MM.yyyy" };
(new[] { "15-01-2019", "15.01.2019" }).Select(s => s.ToDate(patterns)).Dump(); 

which will convert the dates in the array on the fly by using the patterns and dump them to the console.


Some background about TryParseExact

Finally, Here are some comments about the background (i.e. the reason why I have written it this way):

I am preferring TryParseExact in this extension method, because you avoid exception handling - you can read in Eric Lippert's article about exceptions why you should use TryParse rather than Parse, I quote him about that topic:2)

This unfortunate design decision1) [annotation: to let the Parse method throw an exception] was so vexing that of course the frameworks team implemented TryParse shortly thereafter which does the right thing.

It does, but TryParse and TryParseExact both are still a lot less than comfortable to use: They force you to use an uninitialized variable as an out parameter which must not be nullable and while you're converting you need to evaluate the boolean return value - either you have to use an ifstatement immediately or you have to store the return value in an additional boolean variable so you're able to do the check later. And you can't just use the target variable without knowing if the conversion was successful or not.

In most cases you just want to know whether the conversion was successful or not (and of course the value if it was successful), so a nullable target variable which keeps all the information would be desirable and much more elegant - because the entire information is just stored in one place: That is consistent and easy to use, and much less error-prone.

The extension method I have written does exactly that (it also shows you what kind of code you would have to write every time if you're not going to use it).

I believe the benefit of .ToDate(strDateFormat) is that it looks simple and clean - as simple as the original DateTime.Parse was supposed to be - but with the ability to check if the conversion was successful, and without throwing exceptions.


1) What is meant here is that exception handling (i.e. a try { ... } catch(Exception ex) { ...} block) - which is necessary when you're using Parse because it will throw an exception if an invalid string is parsed - is not only unnecessary in this case but also annoying, and complicating your code. TryParse avoids all this as the code sample I've provided is showing.


2) Eric Lippert is a famous StackOverflow fellow and was working at Microsoft as principal developer on the C# compiler team for a couple of years.


var dateStr = @"2011-03-21 13:26";
var dateTime = DateTime.ParseExact(dateStr, "yyyy-MM-dd HH:mm", CultureInfo.CurrentCulture);

Check out this link for other format strings!


DateTime.Parse() should work fine for that string format. Reference:

http://msdn.microsoft.com/en-us/library/1k1skd40.aspx#Y1240

Is it throwing a FormatException for you?


Put the value of a human-readable string into a .NET DateTime with code like this:

DateTime.ParseExact("April 16, 2011 4:27 pm", "MMMM d, yyyy h:mm tt", null);

The simple and straightforward answer -->

using System;

namespace DemoApp.App

{
public class TestClassDate
{
    public static DateTime GetDate(string string_date)
    {
        DateTime dateValue;
        if (DateTime.TryParse(string_date, out dateValue))
            Console.WriteLine("Converted '{0}' to {1}.", string_date, dateValue);
        else
            Console.WriteLine("Unable to convert '{0}' to a date.", string_date);
        return dateValue;
    }
    public static void Main()
    {
        string inString = "05/01/2009 06:32:00";
        GetDate(inString);
    }
}
}

/**
 * Output:
 * Converted '05/01/2009 06:32:00' to 5/1/2009 6:32:00 AM.
 * */

You can also use XmlConvert.ToDateString

var dateStr = "2011-03-21 13:26";
var parsedDate = XmlConvert.ToDateTime(dateStr, "yyyy-MM-dd hh:mm");

It is good to specify the date kind, the code is:

var anotherParsedDate = DateTime.ParseExact(dateStr, "yyyy-MM-dd hh:mm", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);

More details on different parsing options http://amir-shenodua.blogspot.ie/2017/06/datetime-parsing-in-net.html


Try the following code

Month = Date = DateTime.Now.Month.ToString();   
Year = DateTime.Now.Year.ToString(); 
ViewBag.Today = System.Globalization.CultureInfo.InvariantCulture.DateTimeFormat.GetMonthName(Int32.Parse(Month)) + Year;

참고URL : https://stackoverflow.com/questions/5366285/parse-string-to-datetime-in-c-sharp

반응형