C#プログラムに読み込んでいる.CSVファイルがあります。列の1つに日付がありますが、これは「一般」形式であるため、.CSVに数値として表示されます。例:41172。
この数値をC#でdd/mm/yyyy形式の日付に変換するにはどうすればよいですか? 41172は2012年9月20日と同等です。
編集:コメントや他の回答に記載されているように、 DateTime.FromOADate
ははるかに優れたアプローチです。受け入れられない場合は、この回答を削除します。 (ただし、.NET CoreのようにFromOADate
がサポートされていないプラットフォームがまだあるため、これらのプラットフォームを使用しているユーザーにとっては依然として便利です。)
私はあなたが欲しいと思う:
DateTime date = new DateTime(1900, 1, 1).AddDays(days - 2);
(2を引く必要がある理由については、他の回答を参照してください。)
「Excel形式」のDateTimeからC#Date Timeに移動するには、 DateTime.FromOADate 関数を使用できます。
上記の例では:
DateTime myDate = DateTime.FromOADate(41172);
希望の形式で表示するために書き出すには、次を使用します。
myDate.ToString("dd/MM/yyyy");
Excelの日付処理の不一致がどこから来ているのか疑問に思っている場合は、意図的に次のようになっているはずです。
Lotus 1-2-3が最初にリリースされたとき、プログラムは、実際にはうるう年ではなかったにもかかわらず、1900年がうるう年であると想定していました。これにより、プログラムはうるう年を処理しやすくなり、Lotus1-2-3のほとんどすべての日付計算に害はありませんでした。
MicrosoftMultiplanとMicrosoftExcelがリリースされたとき、彼らは1900年がうるう年であると想定していました。これにより、MicrosoftMultiplanとMicrosoftExcelは、Lotus 1-2-3で使用されているのと同じシリアル日付システムを使用し、Lotus1-2-3との互換性を高めることができました。 1900年をうるう年として扱うことで、ユーザーはワークシートをあるプログラムから別のプログラムに簡単に移動できるようになりました。
この動作を修正して、現在のバージョンのMicrosoft Excelが1900年がうるう年であると想定しないようにすることは技術的には可能ですが、そうすることの欠点は利点を上回ります。
.NetCoreでFromOADate
を探している場合、それはありません。
実装.NetFrameworkを分解し、拡張メソッドを作成しました。
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時