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


165

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

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

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

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


19
그렇다면 왜 DateTime.Parse를 사용하지 않습니까?
Austin Salonen

8
나는 downvoters 중 하나였습니다. 원래 질문 ( stackoverflow.com/revisions/… )에서 DateTime.Parse ()를 사용하고 싶다고 말했지만 사용할 수없는 이유를 밝히지 않았기 때문입니다. 이것은 간단한 말로 cacois가 정확하다는 것을 분명히 알았 기 때문에 말도 안되는 질문처럼 보였습니다. 문자열 "2011-03-21 13:26"은 DateTime.Parse ()에 문제가되지 않습니다. 마지막으로, 원래 질문에 ParseExact ()에 대해 언급하지 않았습니다. 당신은 때까지 기다린 미치의 대답은 편집이를 추가 할 수 있습니다.
anon

4
나는 의견에 아무런 이유도없이 사람들에게 투표를 거부하는 사람들을 좋아합니다.
Hooch

답변:


271

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 #의 문자열 형식입니다.


5
수정-항상 안전합니다;) 예외가있는 메소드를 호출하는 경우 가능하면 항상 예외 조건을 먼저 확인하십시오.
Gusdor

3
항상 문화를 전달하는 것이 더 안전하다고 말하고 싶습니다. "01-02-2013"을 1 월 2 일 또는 2 월 1 일로 잘못 해석하는 것보다는 예외가 있습니다.
Carra

1
@Carra : ISO8601 형식의 날짜 (즉, yyyy-mm-dd '는 항상 올바른 방식으로 해석됩니다. 따라서 ISO8601 형식 날짜를 사용하는 이유 ...
Mitch Wheat

정확한 구문 분석이 유용 할 수 있습니다. 때로는 잘못된 출력을 생성하는 대신 응용 프로그램 충돌 및 컴퓨터 불이 켜지는 것을 선호합니다. 응용 프로그램에 따라 다릅니다.
Allen

ParseExact융통성 이 있기 때문에 훌륭하지만 단점이 있습니다. ParseExact 및 Parse 메소드는 variable의 날짜 형식에 구문 오류가있는 경우 예외를 발생시킵니다 s. 따라서 TryParseExcact 를 사용하는 것이 좋습니다 . 아래 답변에서 이유를 지적했습니다.
Matt

47

나중에 설명 할 때 항상 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"연산자와 같은 고급 바로 가기를 사용할 수도 있습니다. ?. .

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: 이것은 (예를 들어, 그렇지 않으면 항상 치료 형식 패턴 같은 방식으로 기능을 강제로 영어에서 소수 구분 기호로 해석 될 수는 그룹 분리하는 동안 "." 또는 날짜 분리기 독일 사람). 문화 기반 형식 문자열을 몇 줄 전에 이미 쿼리 했으므로 여기서는 괜찮습니다.

업데이트 : .ToDate() (매개 변수없이) 이제 스레드의 현재 문화권에 대한 모든 공통 날짜 / 시간 패턴이 기본값으로 설정됩니다.
우리가 필요로 result하고 dt있기 때문에, 서로를 TryParseExact사용하는 것을 허용하지 않습니다 DateTime?우리가 돌아갈 계획. 에서 C # 버전 7 당신은을 단순화 할 수ToDate 다음과 같이 함수를 약간 있습니다.

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

또는 더 짧은 것을 원한다면 :

 // 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?;

이 경우 당신은 두 개의 선언이 필요하지 않습니다 DateTime? result = null;DateTime dt;전혀를 - 당신이 한 줄의 코드에서 그것을 할 수 있습니다. (또한 쓸 수 있습니다out DateTime dtout var dt 원하는 경우 대신 ).

params키워드 를 사용하여 코드를 더 단순화했습니다 . 이제 두 번째 가 필요하지 않습니다. 오버로드 된 메소드가 더 이상 .


사용 예

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!");
}

보시다시피이 예제 dt.HasValue는 변환이 성공했는지 여부를 쿼리 하기 만합니다 . 추가 보너스로 TryParseExact를 사용하면 엄격한 DateTimeStyles날짜 를 지정할 수 있으므로 올바른 날짜 / 시간 문자열이 전달되었는지 여부를 정확하게 알 수 있습니다.


더 많은 사용 예

오버로드 된 함수를 사용하면 여기에 표시된 대로 날짜를 구문 분석 / 변환하는 데 사용되는 유효한 형식배열 을 전달할 수 있습니다 ( 예 : 직접 지원).TryParseExact

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);

템플릿 패턴이 적은 경우 다음과 같이 쓸 수도 있습니다.

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

고급 예

??연산자를 사용하여 기본적으로 오류 방지 형식을 사용할 수 있습니다.

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

이 경우 .ToDate()일반적인 현지 문화 날짜 형식을 사용하고,이 모든 것이 실패하면 ISO 표준 형식 을 사용하려고 합니다."yyyy-MM-dd HH:mm:ss" 을 대체로 합니다. 이런 식으로 확장 기능을 사용하면 다양한 대체 형식을 쉽게 "체인"할 수 있습니다.

LINQ에서 확장을 사용할 수도 있습니다.이 기능을 사용해보십시오 (위의 .NetFiddle에 있음).

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

패턴을 사용하여 즉시 배열의 날짜를 변환하고 콘솔에 덤프합니다.


TryParseExact에 대한 배경

마지막으로, 배경에 대한 의견이 있습니다 (즉, 내가 이런 식으로 쓴 이유).

내가 선호하고 TryParseExact을 당신이 있기 때문에,이 확장 방법에 예외 처리를 방지 작업을 수행 할 수 있습니다 - 예외에 대한 에릭 Lippert의의 기사에서 읽기 : 당신이 아니라 구문 분석에 비해 TryParse를 사용해야하는 이유, 내가 그 주제에 대해 그를 인용 ) (2)

불행한 디자인 결정은 1) [주석 : Parse 메소드가 예외를 던지게하는 것]은 물론 프레임 워크 팀이 TryParse를 곧바로 구현 한 것이 당연한 일이었습니다.

그것은하지만 TryParse, TryParseExact둘 다 사용하기보다 훨씬 적습니다. 초기화되지 않은 변수를 out매개 변수로 사용하여 nullable해서는 안되며 변환하는 동안 부울 반환 값을 평가해야합니다. 사용하기 위해if 즉시 문을하거나 나중에 확인을 할 수있어 있도록 추가 부울 변수에 반환 값을 저장해야합니다. 변환이 성공했는지 여부를 알지 못하면 대상 변수를 사용할 수 없습니다.

대부분의 경우 변환이 성공했는지 여부와 성공한 경우 값 을 알고 싶기 때문에 nullable 대상 변수 모든 정보를 유지 는 전체 정보가 바람직하기 때문에 바람직하고 훨씬 우아합니다. 한곳에 저장 : 일관성 있고 사용하기 쉬우 며 오류가 발생하기 쉽습니다.

내가 작성한 확장 방법은 정확히 수행합니다 (사용하지 않을 때마다 작성해야 할 코드 종류도 보여줍니다).

나는 .ToDate(strDateFormat)그것이 원본처럼 간단하고 깨끗하게 보이지만 DateTime.Parse변환이 성공했는지 여부를 확인하고 예외를 던지지 않고 확인할 수 있는 장점이 있다고 생각합니다 .


1) 여기서 의미 하는 것은 잘못된 문자열이 구문 분석되면 예외를 throw하기 때문에 구문 분석을 사용할 때 필요한 예외 처리 (예 : try { ... } catch(Exception ex) { ...}블록)는이 경우 불필요 할뿐만 아니라 성가신 것입니다. 코드를 복잡하게 만듭니다. TryParse는 내가 제공 한 코드 샘플이 보여주는 것처럼이 모든 것을 피합니다.


2) Eric Lippert는 유명한 StackOverflow 동료 이며 Microsoft에서 C # 컴파일러 팀의 주요 개발자로 2 년 동안 근무했습니다.


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

다른 형식 문자열에 대해서는 이 링크 를 확인하십시오 !



4

사람이 읽을 수있는 문자열의 값을 다음과 같은 코드를 사용하여 .NET DateTime에 넣습니다.

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

2

간단하고 간단한 답변->

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.
 * */

좋은 @ Shivam Bharadwaj, 나는 같은 방식으로
무함마드 Irfan

2

XmlConvert.ToDateString을 사용할 수도 있습니다.

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

날짜 종류를 지정하는 것이 좋습니다. 코드는 다음과 같습니다.

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

다양한 구문 분석 옵션에 대한 자세한 내용 http://amir-shenodua.blogspot.ie/2017/06/datetime-parsing-in-net.html


0

다음 코드를 사용해보십시오

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

안녕하세요, 질문에 답변 할 때 설명을 제공해주십시오. 코드를 게시하는 것은 권장하지 않습니다
Ali
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.