在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
小时在哪里?
答案 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));
}
请注意:
那当然会让你的问题是“小时在哪里?”不相关 - 但答案就是SimpleDateFormat
默认使用系统时区,所以你实际上是依赖于你正在运行测试的系统的时区,这是一个真的坏主意。如果你将SimpleDateFormat
的时区设置为UTC,你会发现它在Java中也是07:35:11。
答案 1 :(得分:2)
您使用的constructor将ticks作为第一个参数,但是您传递的值是毫秒。
Ticks:日期和时间,以公历1月1日(公元01年1月1日00:00:00.000)开始的100纳秒间隔数表示。
答案 2 :(得分:1)