5

std::time_t値の変換とその逆の変換に関連するいくつかの回答が既に見つかりましSystem::DateTimeた。ただし、ほとんどすべての回答は、 の型std::time_tが実際には標準で定義されていないことを無視しているようです。ほとんどのソリューションは、必要なものにキャストstd::time_tするか、算術型であるため可能なオブジェクトに算術演算を適用するだけstd::time_tですが、そのような演算の結果に関する仕様はありません。ほとんどのコンパイラが をある程度のサイズで定義time_tしていることは知っていますが、最近多くの実装でからにint変更されたという事実だけでも、変更が実際に可能であることを示しています。int32int64

だから私はこのソリューションを思いついたstd::time_t. それは私が見たものから機能します。しかし、私は疑問に思っていました-私が気付いていない可能性のある落とし穴はありますか?

template <>
inline System::DateTime marshal_as(const std::time_t &from_object)
{
    // Returns DateTime in Local time format from time_t (assumed to be UTC)
    const auto unix_epoch = makeUtcTime(1970, 1, 1, 0, 0, 0);
    const auto unix_epoch_dt = System::DateTime(1970, 1, 1, 0, 0, 0, System::DateTimeKind::Utc);
    const auto secondsSinceEpoch = std::difftime(from_object, unix_epoch);
    return const_cast<System::DateTime&>(unix_epoch_dt).AddSeconds(secondsSinceEpoch).ToLocalTime();
} // end of System::DateTime marshal_as(const std::time_t &from_object)

template <>
inline std::time_t marshal_as(const System::DateTime &from_object)
{
    // Returns time_t in UTC format from DateTime
    auto from_dt = const_cast<System::DateTime&>(from_object).ToUniversalTime();
    return makeUtcTime(from_dt.Year, from_dt.Month, from_dt.Day, from_dt.Hour, from_dt.Minute, from_dt.Second);
} // end of std::time_t marshal_as(const System::DateTime &from_object)

3 つの仮定が行われました。

  • std::time_tローカリゼーションに関する情報が含まれていないため、結果は UTC である必要があります
  • ローカライズされた値を返すため、結果System::DateTimeは現地時間である必要がありますSystem::DateTime::NowDateTime
  • makeUtcTimestd::tmは、指定された値から を作成し、そこから UTC を作成するヘルパー関数std::time_tです。_mkgmtime相互運用コードは Microsoft 拡張機能の存在に安全に依存できるため、これは現在 を使用して実装されています。ただし、 の UTC バージョンはmktime、他のコンパイラでもすぐに利用できます (標準でmktimeは現地時間が必要です)。

考慮すべき重要度の低い 2 つの点:

  • これconst_castが必要なのは、marshal_as-template がconst T&as パラメーターを想定しており、const .NET 値型オブジェクトのプロパティにアクセスできないためです。ただし、より良い解決策があるかもしれません。
  • unix_epoch...ものはあるべきですstatic constか?

(これは「Programmers Exchange」に投稿する必要があるかどうかはわかりませんでした。これはより議論が多いためですが、非常に具体的なC ++の質問であるため、SOが質問するのに適していると思いました)

4

2 に答える 2

0

私のチームが到達したソリューションは次のとおりです。

DateTime は、1899 年 12 月 30 日の午前 0 時以降の小数部の日数を double で表したものです。このエポック日付は、1900 年が閏年ではなく、さらに 2 日を許容するために使用されたものだと思います (なぜ 1 日ではなく 2 日なのか? - なぜ 1899 年 12 月 31 日がそうでなかったのかは私には明らかではありません)。時代として選ばれました。)

したがって、2.50 の DateTime は 1900 年 1 月 1 日 12:00:00 と同等です (つまり、分数は 1/2 日 - 12PM を表します)。

1970 年 1 月 1 日 (Unix エポック) は、DateTime エポックから 25569 日後です。

したがって、同等の式は次のようになります。

#include <time.h>
System::DateTime toDateTime(time_t &t)
{
    return 25569.0 + t / 86400.0; // ensure you use floating point math or you will truncate the fractional portion
}
于 2014-09-26T20:25:26.453 に答える