.net - 将 std::time_t 转换为 System::DateTime 的标准符合方式?

标签 .net datetime c++-cli mixed-mode time-t

我已经找到了几个与转换 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&作为参数,我无法访问 const .NET 值类型对象的属性。但是,可能有更好的解决方案。
  • unix_epoch...东西是static const ?

  • (我不确定这是否应该发布在“Programmers Exchange”上,因为它更像是一个讨论,但由于它是一个非常具体的 C++ 问题,我认为 SO 可能是更好的提问地点)

    最佳答案

    坚持以“标准符合”的方式进行这种转换并不是很有成效。 Ecma-372 standard 涵盖了 std::time_t 和 System::DateTime 唯一相遇的地方。 .其中现在有,而且将来肯定有,只有 执行。 Mono 项目可能被认为是另一个项目的最可能来源,但现在他们似乎对提供混合模式实现完全不感兴趣,这是您考虑使用 C++/CLI 的唯一原因。

    std::time_t 正在稳步迈向 Y2K38 灾难。微软先发制人地对此采取了一些措施,并且确实不得不这样做,因为他们选择了 LLP64,但其他所有人都指望他们的 LP64 data model让他们远离麻烦。换句话说,2038 年没有剩余的 32 位处理器仍在运行。这很可能是一个自我实现的预言。

    无论如何,转换必须使用自 1970 年 1 月 1 日以来经过的秒数。这可以是 32 位或 64 位整数值,具体取决于实现。我能提供的唯一保证是此代码至少在 2038 年之前都有效:

    #include <ctime>
    
    using namespace System;
    
    public ref class Conversions {
    public:
        static DateTime time_t2DateTime(std::time_t date) {
            double sec = static_cast<double>(date);
            return DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind::Utc).AddSeconds(sec);
        }
        static std::time_t DateTime2time_t(DateTime date) {
            TimeSpan diff = date.ToUniversalTime() - DateTime(1970, 1, 1);
            return static_cast<std::time_t>(diff.TotalSeconds);
        }
    };
    

    关于.net - 将 std::time_t 转换为 System::DateTime 的标准符合方式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21265481/

    相关文章:

    c# - 反转队列

    .net - 免费语法突出显示 .NET 编辑器

    asp.net - 如何为自动 C++/CLI 应用程序域指定 ASP.NET 探测路径?

    visual-studio-2012 - 尝试向 C++/CLI 项目添加资源时拒绝访问

    .net - C++/CLI 程序集中定义的 Powershell 和枚举

    c# - 尝试为链接/浏览器获取 WatiN

    .net - 在 Silverlight 中将代码隐藏添加到资源字典时出现 xClassNotDerivedFromElement 错误

    datetime - 两个 localDate 之间的区别

    python - 当我附加时,Numpy 错误地将大 float 更改为非常小的数字

    python - 将 JSON 时间戳字符串转换为 pandas dataframe 中的 python 日期