programing

문자열을 C#의 DateTime에 구문 분석

goodsources 2023. 9. 13. 22:34
반응형

문자열을 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#에서의 String Formating입니다.

내가 나중에 설명하는 것처럼, 나는 항상 그것을 선호할 것입니다.TryParse그리고.TryParseExact방법들.사용하기에는 부피가 좀 크기 때문에 구문 분석을 훨씬 쉽게 할 수 있는 확장 방법을 작성했습니다.

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

또는 현재 문화의 날짜 패턴을 암시적으로 사용하려면 다음과 같이 사용할 수 있습니다.

 DateTime? dt = dtStr.ToDate();

그런 경우에는 특정 패턴을 지정할 필요가 없습니다.지정하지 않으면 현재 스레드에 있는 현재 문화의 기본 DateTime 패턴이 사용됩니다.

와는 달리Parse,ParseExact등. 예외를 두지 않으며, 다음을 통해 확인할 수 있습니다.

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

변환이 성공했는지 여부(이 경우)dt다음을 통해 액세스할 수 있는 값이 있습니다.dt.Value) 또는 없음(이 경우 해당)null).

그것은 심지어 "엘비스" 운영자처럼 우아한 단축키를 사용할 수 있게 해줍니다.?., 예를 들어 다음과 같습니다.

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

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


해결책:  .ToDate() 확장 메서드

해보세요.넷피들

public static class Extensions
{
  /// Extension method parsing a date string to a DateTime? <para/>
  /// <summary>
  /// </summary>
  /// <param name="dateTimeStr">The date string to parse</param>
  /// <param name="dateFmt">dateFmt is optional and allows to pass 
  /// a parsing pattern array or one or more patterns passed 
  /// as string parameters</param>
  /// <returns>Parsed DateTime or null</returns>
  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();
    }
    var result = DateTime.TryParseExact(dateTimeStr, dateFmt, CultureInfo.InvariantCulture,
                   style, out var dt) ? dt : null as DateTime?;
    return result;
  }
}

코드에 대한 몇 가지 정보

내가 왜 이런 걸 썼는지 궁금하실 겁니다.InvariantCulture부르기TryParseExact: 이것은 함수가 항상 동일한 방식으로 형식 패턴을 처리하도록 강제하기 위함입니다(예를 들어, "."는 영어로 10진수 구분자로 해석할 수 있지만 그룹 구분자 또는 날짜 구분자는 독일어로 해석할 수 있습니다).우리는 이미 몇 줄 전에 문화 기반 형식 문자열을 조회했으므로 여기서는 괜찮습니다.

업데이트: .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 dt대신에out var dt원하신다면요)

C#의 이전 스타일은 다음과 같은 방식으로 요구했을 것입니다(위의 코드에서 제거했습니다).

  // DateTime? result = null;
  // DateTime dt;
  // if (DateTime.TryParseExact(dateTimeStr, dateFmt,
  //    CultureInfo.InvariantCulture, style, out dt)) result = dt;

나는 코드를 더 단순화 시켰습니다.params키워드:이제 당신은 2개의nd 오버로드된 방법이 더 이상 필요 없습니다.


사용 예시

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 strDateArray = new[] { "15-01-2019", "15.01.2021" };
var patterns=new[] { "dd-MM-yyyy", "dd.MM.yyyy" };
var dtRange = strDateArray.Select(s => s.ToDate(patterns));
dtRange.Dump(); 

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


TryParseExact에 대한 몇 가지 배경

마지막으로 배경에 대한 몇 가지 의견(즉, 제가 이렇게 쓴 이유)을 소개합니다.

저는 이 확장 방법에서 TryParseExact를 선호합니다. 예외 처리를 피할 수 있기 때문입니다. Eric Lippert의 기사에서 Parse가 아닌 TryParse를 사용해야 하는 예외3) 대한 기사를 읽을있습니다. 저는 2)이 주제에 대해 그의 말을 인용합니다.

유감스러운 설계1) 결정[주석: Parse 메서드가 예외를 허용하도록 하는 것]은 매우 번거로웠기 때문에 프레임워크 팀은 곧 올바른 작업을 수행하는 TryParse를 구현했습니다.

있습니다만.TryParse그리고.TryParseExact두 가지 모두 여전히 사용하기에 훨씬 불편합니다.초기화되지 않은 변수를 사용하도록 강제합니다.outnull이 되어서는 안되며 변환하는 동안 부울 리턴 값을 평가해야 합니다 - 를 사용해야 합니다.ifstatement를 즉시 사용하거나 반환 값을 추가 부울 변수에 저장해야 나중에 확인할 수 있습니다.그리고 변환이 성공했는지 여부를 모른 채 목표 변수만 사용할 수는 없습니다.

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

제가 작성한 확장 방법이 바로 그것입니다. (사용하지 않을 경우 매번 어떤 코드를 작성해야 하는지도 보여줍니다.)

나는 그들이 가진 것을 믿습니다..ToDate(strDateFormat)단순하고 깨끗해 보이기 때문입니다 - 원작처럼 단순합니다.DateTime.Parse원래는 - 하지만 변환이 성공했는지 확인할 수 있는 기능과 함께 예외를 두지 않습니다.


1) 여기서 의미하는 것은 예외 처리(즉,try { ... } catch(Exception ex) { ...} block) - 잘못된 문자열을 구문 분석하면 예외가 발생하기 때문에 구문 분석을 사용할 때 필요합니다. 이 경우 불필요할 뿐만 아니라 코드가 성가시고 복잡합니다.트라이파스는 제가 제공한 코드 샘플이 보여주므로 이 모든 것을 피합니다.


2) Eric Lippert유명한 StackOverflow 연구원으로 마이크로소프트에서 몇 년 동안 C# 컴파일러 팀의 수석 개발자로 일하고 있었습니다.

3) 안타깝게도 마이크로소프트는 MSDN 사이트에서 이 기사를 삭제했습니다.다른 URL에서 찾으시는 분이 있으면 알려주시면 업데이트 해드리겠습니다.

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

다른 형식 문자열은 이 링크를 확인해 보세요!

날짜 시간.구문 분석()은 해당 문자열 형식에 대해 정상적으로 작동해야 합니다.참조:

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

포맷 예외가 발생하는 건가요?

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

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

XmlConvert를 사용할 수도 있습니다.ToDate 문자열

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

간단하고 직설적인 답 -->

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

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

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

날짜 시간.ParseExact(DateTime, Format, DateTimeFormatInfo).불변 정보, DateTimeStyle.선도 허용흰색 | 날짜 시간 스타일.추적 허용흰색)

예를 들어 다음과 같습니다.

날짜 시간.ParseExact("2011-03-21 13:26", "yyyy-MM-dd hh:mm", DateTimeFormatInfo.불변 정보, DateTimeStyle.선도 허용흰색 | 날짜 시간 스타일.추적 허용흰색);

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

반응형