c# - DateTime 转换为 Unix Epoch 添加 Phantom Hour

标签 c# datetime timezone unix-timestamp epoch

我有以下转换方法来转换 Unix Epoch 时间戳

public static class DateTimeHelpers
{
    public static DateTime UnixEpoch()
    {
        return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
    }

    public static DateTime FromMillisecondsSinceUnixEpoch(long milliseconds)
    {
        return UnixEpoch().AddMilliseconds(milliseconds).ToLocalTime();
    }

    public static long ToMillisecondsSinceUnixEpoch(DateTime dateTime)
    {
        return (long)(dateTime - UnixEpoch()).TotalMilliseconds;
    }
}

问题是(男孩,这看起来像是基本的东西),我设置了一个我想要的 DateTime 然后尝试转换为 Unix-Time 但返回的毫秒时间戳是 +01:00 小时,我想知道为什么吗?

我使用的代码是

DateTime startDate = new DateTime(2015, 10, 1, 0, 0, 0, 0, DateTimeKind.Utc);

long startMillis = DateTimeHelpers.ToMillisecondsSinceUnixEpoch(startDate);

这给出 startMillis = 1443657600000,它是“2015 年 10 月 1 日星期四 01:00:00 (am) 在时区欧洲/伦敦 (BST)”。我想要从 ToMillisecondsSinceUnixEpoch 返回的时间戳,即“2015/10/01 00:00:00”,我在这里缺少什么?

感谢您的宝贵时间。


编辑。我想做一些 Java 代码的等价物。这产生了正确的时间戳。为什么我可以在 Java 而不是 C# 中执行此操作?不管怎样代码

private static long ukTimeStringToUtcMillis(String s) {
    SimpleDateFormat sdf = makeSimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
    try {
        return sdf.parse(s).getTime();
    } catch (ParseException e) {
        throw new RuntimeException(e);
    }
}

private static SimpleDateFormat makeSimpleDateFormat(String s) {
    SimpleDateFormat sdf = new SimpleDateFormat(s);
    sdf.setTimeZone(TimeZone.getTimeZone("Europe/London"));
    return sdf;
}

我是这样用的

long timestamp = ukTimeStringToUtcMillis("2015-10-01T00:00:00.000");

这给出了 timestamp = 1443654000000,它是“2015 年 10 月 1 日星期四 00:00:00 (am) 在时区欧洲/伦敦 (BST)”。我在 C# 中缺少什么?我试过了

var ukTimeZone = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
DateTime unixEpoch = TimeZoneInfo.ConvertTime(
    new DateTime(1970, 1, 1, 0, 0, 0), ukTimeZone, ukTimeZone);

long startMillis = (long)(startDate - unixEpoch).TotalMilliseconds;
long endMillis = (long)(endDate - unixEpoch).TotalMilliseconds;

这增加了一个小时!?

最佳答案

如果我按照您的操作进行操作,您的测试代码将以 UTC 时间开始:

DateTime startDate = new DateTime(2015, 10, 1, 0, 0, 0, 0, DateTimeKind.Utc);

但在 FromMillisecondsSinceUnixEpoch 中,您返回 LocalTime。按原样使用代码,它不会进行往返:

Console.WriteLine(dt.ToUniversalTime());
Console.WriteLine("{0}  {1}", ToMillisecondsSinceUnixEpoch(dt), 
    FromMillisecondsSinceUnixEpoch(ToMillisecondsSinceUnixEpoch(dt)));

10/1/2015 5:00:00 AM
1443657600000 10/1/2015 12:00:00 AM

如果我更改 FromMillisecondsSinceUnixEpoch:

public static DateTime FromMillisecondsSinceUnixEpoch(long milliseconds)
{
    return UnixEpoch().AddMilliseconds(milliseconds).ToUniversalTime();
}

现在它将进行往返:

10/1/2015 5:00:00 AM
1443675600000 10/1/2015 5:00:00 AM

请注意,每个 MilliSecondsSince 都是相同的。你不能只看那个,因为没有上下文。

我无法在引用源中找到它,但 DateTime 肯定足够聪明,可以在 TZ 不同时进行调整,然后再进行减法。 (否则很难解释 1443675600000 如何代表同一日期的 3 个时间跨度(2 个给我,1 个给你)。

关于c# - DateTime 转换为 Unix Epoch 添加 Phantom Hour,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33451858/

相关文章:

javascript - 在 IE 中将 c# 文本框作为 javascript 参数传递(Chrome 有效)

C# Generics Efficiency,一种更好的方法

c# - Visual C# 2010 Express Edition - 当我按 F5 时,是否存储创建的文件?

c# - 数据表访问C#

r - 在R中将UTC时间转换为本地标准时间

timezone - CLDR 时区 xml 中英语示例城市的完整列表在哪里?

python - 有没有办法从国家或时区获取语言环境?

c# - 如何将 DateTime 现在转换为秒

android - 字符串到日期时间的转换 : Android

php - 时区计算。 PHP 函数与 MySQL 函数