C# プログラムに読み込んでいる .CSV ファイルがあります。列の 1 つに日付がありますが、これは「一般的な」形式であるため、.CSV では数値として表示されます。例: 41172。
この数値をC#でdd/mm/yyyy形式の日付に変換するにはどうすればよいですか? 41172 は 2012 年 9 月 20 日と同等です。
C# プログラムに読み込んでいる .CSV ファイルがあります。列の 1 つに日付がありますが、これは「一般的な」形式であるため、.CSV では数値として表示されます。例: 41172。
この数値をC#でdd/mm/yyyy形式の日付に変換するにはどうすればよいですか? 41172 は 2012 年 9 月 20 日と同等です。
「Excel 形式」の DateTime から C# Date Time に移行するには、DateTime.FromOADate関数を使用できます。
上記の例では:
DateTime myDate = DateTime.FromOADate(41172);
目的の形式で表示するために書き出すには、次を使用します。
myDate.ToString("dd/MM/yyyy");
Excel の日付処理の不一致がどこから来るのか疑問に思っている場合、それは意図的なものであるはずです:
Lotus 1-2-3 が最初にリリースされたとき、プログラムは 1900 年が実際にはうるう年ではなくても、うるう年であると想定していました。これにより、プログラムはうるう年を簡単に処理できるようになり、Lotus 1-2-3 のほぼすべての日付計算に悪影響を与えることはありませんでした。
Microsoft Multiplan と Microsoft Excel がリリースされたときも、1900 年がうるう年であると想定されていました。これにより、Microsoft Multiplan と Microsoft Excel は、Lotus 1-2-3 と同じシリアル日付システムを使用できるようになり、Lotus 1-2-3 との互換性が向上しました。1900 年をうるう年として扱うことで、ユーザーはワークシートをあるプログラムから別のプログラムに移動しやすくなりました。
現在のバージョンの Microsoft Excel で 1900 年がうるう年であると想定されないように、この動作を修正することは技術的に可能ですが、その欠点は利点を上回ります。
編集:コメントやその他の回答に記載されているようにDateTime.FromOADate
、はるかに優れたアプローチです。受け入れられない場合は、この回答を削除します。(ただし、サポートされていない .NET Core のようなプラットフォームFromOADate
がまだあるため、これらのプラットフォームを使用しているユーザーにとっては依然として有用です。)
私はあなたが欲しいと思う:
DateTime date = new DateTime(1900, 1, 1).AddDays(days - 2);
(2を引く必要がある理由については、他の回答を参照してください。)
FromOADate
.Net Core で探している場合、そこにはありません。
.Net Framework の実装を逆アセンブルし、拡張メソッドを作成しました。
public static DateTime FromOADate(this double date)
{
return new DateTime(DoubleDateToTicks(date), DateTimeKind.Unspecified);
}
internal static long DoubleDateToTicks(double value)
{
if (value >= 2958466.0 || value <= -657435.0)
throw new ArgumentException("Not a valid value");
long num1 = (long)(value * 86400000.0 + (value >= 0.0 ? 0.5 : -0.5));
if (num1 < 0L)
num1 -= num1 % 86400000L * 2L;
long num2 = num1 + 59926435200000L;
if (num2 < 0L || num2 >= 315537897600000L)
throw new ArgumentException("Not a valid value");
return num2 * 10000L;
}
まだテストする必要があります。
Excel で使用される日付形式は古いものですが、この数値を変換するために使用できるDateTime.FromOADate関数で引き続きサポートされています。次のように定義されます。
基準日である 1899 年 12 月 30 日の午前 0 時からの前後の日数
MSDN からこれを見たことがあります: http://msdn.microsoft.com/en-us/library/system.datetime.fromoadate.aspx、しかし実際には間違っていると思います。
本当の問題は、Excel が世紀の年 (1900 年) を閏年であると誤って想定しているのに対し、実際には閏年ではなく、2000 年だったことです。
これを確認するには、Excel でセルを日付としてフォーマットしてから入力1
してみてください1 Jan 1900
。入力する59
と、 が得られ28 Feb 1900
ます。(実際の日付ではない) を与え、次に60
を与えます。29 Feb 1900
61
01 March 1900
そう...
switch (days)
{
case < 1:
// Not valid. Do whatever...
break;
case < 59:
DateTime date = new DateTime(1900, 1, 1).AddDays(days);
break;
default:
// Knock off the extra days caused by 29 Feb 1900 and 29 Feb 2000
DateTime date = new DateTime(1900, 1, 1).AddDays(days-2);
break;
}