Java与C#长期到日期时间转换

时间:2015-02-13 16:22:17

标签: java c# datetime date-conversion

在Java中,我有以下测试通过

// 42 bits of time is good enough for the next 100 years.
// An IEEE double has 52 bits of mantissa, so our dates can be easily fit.
@Test
public void testMaxBits() throws ParseException {
    // Maximum 42 bit integer
    long millis = (1L << 42) - 1;
    Date date = new Date(millis);
    //DateTime maxDate = new DateTime(2109, 5, 15, 8, 35, 11, 103);
    Date maxDate = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS").parse("2109-05-15T08:35:11.103");
    Assert.assertEquals(maxDate, date);
}

现在,我想在C#中做同样的事情,所以我在LinqPAD中测试了C#实现的正确性

DateTime maxDate = new DateTime(2109, 5, 15, 8, 35, 11, 103);
long beginTicks = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks;
long l = (1L << 42) - 1;
DateTime date = new DateTime(beginTicks + l, DateTimeKind.Utc);
maxDate.Dump();
date.Dump();

输出不匹配,输出的值ToString()

  

maxDate = 15/05/2109 08:35:11   date = 06/01/1970 02:10:04

我在这里缺少什么?


编辑。我在@zmitrok看到了一个很好的答案,我已经改变了

DateTime date = new DateTime(beginTicks + l, DateTimeKind.Utc);

DateTime date = new DateTime(beginTicks + 
    l * TimeSpan.TicksPerMillisecond, DateTimeKind.Utc);

但现在获得

  

date = 15/05/2109 07:35:11

小时在哪里?

3 个答案:

答案 0 :(得分:7)

您的测试基本上会将滴答声与毫秒相混淆。如果你只需要存储自unix时代以来的毫秒数,那么这样做 - 但我建议使用这样的东西来执行转换:

public static readonly DateTime UnixEpoch
    = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

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

(作为旁注,我that method already exists项目中的Noda Time ...暗示提示:)

您的测试将是:

[TestMethod]
public void TestMaxBits()
{
    long maxMillis = (1L << 42) - 1;
    DateTime maxDate = DateTimeHelper.FromMillisecondsSinceUnixEpoch(maxMillis);
    Assert.Greater(maxDate, new DateTime(2100, 1, 1, 0, 0, 0));
}

请注意:

  • 此代码根本没有提及刻度,因为您对刻度不感兴趣
  • 此代码并未声明最大日期是某个非常具体的值,因为这不是您关心的;你关心42位时间会带你到本世纪末。 (“未来100年”的评论有些似是而非,因为2109离现在不到100年,所以我认为它真的意味着“直到21世纪末。”)

那当然会让你的问题是“小时在哪里?”不相关 - 但答案就是SimpleDateFormat默认使用系统时区,所以你实际上是依赖于你正在运行测试的系统的时区,这是一个真的坏主意。如果你将SimpleDateFormat的时区设置为UTC,你会发现它在Java中也是07:35:11。

答案 1 :(得分:2)

您使用的constructor将ticks作为第一个参数,但是您传递的值是毫秒。

  

Ticks:日期和时间,以公历1月1日(公元01年1月1日00:00:00.000)开始的100纳秒间隔数表示。

答案 2 :(得分:1)