解释到UnixTimeMilliseconds

Posted

技术标签:

【中文标题】解释到UnixTimeMilliseconds【英文标题】:Explain ToUnixTimeMilliseconds 【发布时间】:2020-02-11 22:02:44 【问题描述】:

我正在尝试找到更好的方法在 C# 中将 DateTime 转换为 unix 时间戳

我发现有一个 DateTimeOffset.ToUnixTimeMilliseconds 方法:

public long ToUnixTimeMilliseconds()

   return this.UtcDateTime.Ticks / 10000L - 62135596800000L;

这个方法是什么意思? 常量使用什么?

更新: 我猜 10000L 正在从 FRAME 转换为毫秒。但是62135596800000L呢?

【问题讨论】:

Unix 时间基于 1970 年 1 月 1 日午夜 UTC 的“纪元”。 为什么你想让 Unix 时间戳开始?数据库有日期类型,它们不需要 Unix 时间戳。 Web 应用程序已经处理日期。 JSON 使用 ISO8601 作为事实上的标准。没关系时区 和夏令时。即使将所有内容存储为 UTC 也不足以消除歧义 我需要它来与其他系统集成 【参考方案1】:

解释这个方法:

public long ToUnixTimeMilliseconds()

    return this.UtcDateTime.Ticks / 10000L - 62135596800000L;

DateTime.Ticks 单位是 100 纳秒间隔。

将其除以 10_000 得到毫秒,这解释了除以 10000L。

这是因为一纳秒是十亿分之一秒,或百万分之一毫秒。

要将纳秒转换为毫秒,您需要除以 1_000_000。

但是,刻度是 100 纳秒单位,因此您必须除以 1_000_000/100 = 10_000,而不是除以 1_000_000。这就是为什么将 100 纳秒单位除以 10_000 得到毫秒的原因。

Unix 纪元(对应于 Unix 时间为零)是 1970 年 1 月 1 日午夜。

DateTime 纪元(对应于 DateTime.Ticks 值为零)是 0001 年 1 月 1 日。

0001 年 1 月 1 日到 1970 年 1 月 1 日之间的毫秒数是 62135596800000。这解释了 62135596800000 的减法。

你有它!

注意:您可以计算毫秒数的近似值,如下所示:

Approximate number of days per year = 365.24219 
Number of years between 0001 and 1970 = 1969 
Thus, total approx milliseconds = 1969 * 365.24219 * 24 * 60 * 60 * 1000
= 62135585750000

确切的数字更难计算,但根据上面的公式得出的结果是 62135596800000。

事实上,通过查看the source code我们可以发现:

public long ToUnixTimeSeconds() 
    // Truncate sub-second precision before offsetting by the Unix Epoch to avoid
    // the last digit being off by one for dates that result in negative Unix times.
    //
    // For example, consider the DateTimeOffset 12/31/1969 12:59:59.001 +0
    //   ticks            = 621355967990010000
    //   ticksFromEpoch   = ticks - UnixEpochTicks                   = -9990000
    //   secondsFromEpoch = ticksFromEpoch / TimeSpan.TicksPerSecond = 0
    //
    // Notice that secondsFromEpoch is rounded *up* by the truncation induced by integer division,
    // whereas we actually always want to round *down* when converting to Unix time. This happens
    // automatically for positive Unix time values. Now the example becomes:
    //   seconds          = ticks / TimeSpan.TicksPerSecond = 62135596799
    //   secondsFromEpoch = seconds - UnixEpochSeconds      = -1
    //
    // In other words, we want to consistently round toward the time 1/1/0001 00:00:00,
    // rather than toward the Unix Epoch (1/1/1970 00:00:00).
    long seconds = UtcDateTime.Ticks / TimeSpan.TicksPerSecond;
    return seconds - UnixEpochSeconds;


// Number of days in a non-leap year
private const int DaysPerYear = 365;
// Number of days in 4 years
private const int DaysPer4Years = DaysPerYear * 4 + 1;       // 1461
// Number of days in 100 years
private const int DaysPer100Years = DaysPer4Years * 25 - 1;  // 36524
// Number of days in 400 years
private const int DaysPer400Years = DaysPer100Years * 4 + 1; // 146097

// Number of days from 1/1/0001 to 12/31/1600
private const int DaysTo1601 = DaysPer400Years * 4;          // 584388
// Number of days from 1/1/0001 to 12/30/1899
private const int DaysTo1899 = DaysPer400Years * 4 + DaysPer100Years * 3 - 367;
// Number of days from 1/1/0001 to 12/31/1969
internal const int DaysTo1970 = DaysPer400Years * 4 + DaysPer100Years * 3 + DaysPer4Years * 17 + DaysPerYear; // 719,162        

我们现在可以用它来计算到 1970 年的毫秒数:

719162 (DaysTo1970) * 24 (hours) * 60 (minutes) * 60 (seconds) * 1000 (milliseconds) 
= 621355967990000

【讨论】:

@Mathew Watson 你能解释一下除以 10,000 得到 100000L 的部分吗,我不明白。为什么要除以 10,000? @JohnChris 我已将其添加到答案中,但如果您知道纳秒和毫秒是什么,那肯定是显而易见的...... 我同意这对某些人来说是显而易见的,但不是全部,现在更好的答案:)

以上是关于解释到UnixTimeMilliseconds的主要内容,如果未能解决你的问题,请参考以下文章

linux--切换ipython解释器到python3

PyCharm 没有检测到解释器

3Dmax9.0中英文命令的全部中文解释?

将php代码保存到文件中而不解释它

Javascript 文件在发送到客户端之前是不是由服务器解释? [关闭]

Android的问题:能解释一下else里边的onBackPressed()方法是返回到哪里去吗?