そのようにフォーマットされた文字列に日付と時刻があります。
"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メソッドのいずれかを使用するほうが安全です)。
フォーマット文字列を作成するときは、 カスタムの日付と時刻のフォーマット文字列 を必ず確認してください。
C#形式の文字列に関するもう1つの便利なリソースは、 C#での文字列フォーマット です。
後で説明するように、私は常にTryParse
および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
です)。
これにより、「エルビス」演算子?.
のようなエレガントなショートカットを使用することもできます。例:
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?
// 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
を使用したのか疑問に思うかもしれません:これは、関数にフォーマットパターンを常に同じように処理させるためです(そうでなければ、たとえば "。"は英語の小数点区切りとして解釈されます)グループ区切り文字ですorドイツ語の日付区切り文字)。数行前に既にカルチャーベースのフォーマット文字列を照会したことを思い出してください。ここでは大丈夫です。
更新:.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?;
この場合、2つの宣言DateTime? result = null;
とDateTime dt;
はまったく必要ありません-1行のコードで実行できます。 (必要に応じて、out DateTime dt
の代わりにout var 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
を指定できるため、適切な日付/時刻文字列が渡されたかどうかを正確に知ることができます。
その他の使用例
オーバーロード関数を使用すると、日付の解析/変換に使用される有効な形式の配列配列を渡すことができます here 同様に(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標準 format "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を好んでいます、なぜならあなたは例外処理を避けるためです -できます 例外についてのEric Lippertの記事を読んでください なぜParseではなくTryParseを使用する必要があるのか、そのトピックについて彼に引用します:2)
この残念なデザインの決定1) [注釈:Parseメソッドが例外をスローできるようにする]がとても厄介だったので、フレームワークチームはすぐにTryParseを実装しましたこれは正しいことです。
ただし、TryParse
とTryParseExact
はどちらも使用するのがあまり快適ではありません。初期化されていない変数をout
パラメーターとして使用するように強制します。 '変換している場合、ブール値の戻り値を評価する必要があります-if
statementをすぐに使用するか、戻り値を追加のブール変数に保存して後でチェックできるようにする必要があります。そして、変換が成功したかどうかを知らずにターゲット変数を使用することはできません。
ほとんどの場合、知りたいのは変換が成功したかどうか(そしてもちろん成功した場合は値)なので、nullableターゲット変数すべての情報を保持することが望ましいとはるかにエレガントになります-情報全体が1か所に保存されるためです:それは一貫性があり、使いやすく、エラーが少ないです。
私が書いた拡張メソッドはまさにそれを行います(使用しない場合は毎回どのようなコードを書かなければならないかを示しています)。
.ToDate(strDateFormat)
の利点は、元のDateTime.Parse
のようにシンプルできれいに見えることですが、変換が成功したかどうかを確認し、例外をスローしないことです。
1) ここで意味するのは、例外処理(つまりtry { ... } catch(Exception ex) { ...}
ブロック)-これは、Parseを使用している場合に必要です。無効な文字列が解析されます-この場合は不要であるだけでなく、迷惑でコードを複雑にします。 TryParseは、提供したコードサンプルが示しているように、これをすべて回避します。
2) Eric Lippertは有名な StackOverflowの仲間 であり、MicrosoftでC#コンパイラチームの主な開発者として数年間働いていました。
var dateStr = @"2011-03-21 13:26";
var dateTime = DateTime.ParseExact(dateStr, "yyyy-MM-dd HH:mm", CultureInfo.CurrentCulture);
他のフォーマット文字列については、--- link をチェックしてください。
DateTime.Parse()はその文字列フォーマットに対してはうまく動作するはずです。参照:
http://msdn.Microsoft.com/ja-jp/library/1k1skd40.aspx#Y124
それはあなたのためにFormatExceptionを投げていますか?
このようなコードを使用して、人間が読める文字列の値を.NETのDateTimeに入れます。
DateTime.ParseExact("April 16, 2011 4:27 pm", "MMMM d, yyyy h:mm tt", null);
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
単純明快な答え - >
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;