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