【问题标题】:Comparing datenum and 18 digit timestamps比较 datenum 和 18 位时间戳
【发布时间】:2017-10-27 21:22:05
【问题描述】:

我得到了两次戳记,我想在几秒钟内知道它们的区别。两个时间戳都接近

5-9-2012 17:42:01

几小时内(7 小时)。

从信号 1 开始,我们有一个 18 位的时间戳 (6.348246372197819e+17)。时间戳从 1.JAN.0001 开始以 100 纳秒计算。我猜它是.NET 时间戳(如果有人知道那个时间戳的具体名称,那就太好了)。 (从戳中查看timestr:)

TS1=System.DateTime(int64(TS_signal1));
TS1.ToString

从信号 2 开始,我们有一个 16 位的时间戳 (735117.446046926)。 (我猜来自 Matlab datenum 的序列号)。如果我没记错的话,Datenum 是从 0.JAN.0000 开始的小数天。

时间戳 1 可以通过乘以 10^-7(100Ns 分辨率)轻松转换为秒。

时间戳 2 是通过乘以 24*3600 来转换的,对吗? (哪个分辨率有datenum [10ms?]?乘法后序列号是浮点数:63514147338.4544)

现在,问题是时间戳不会同时开始计数。我也没有关于 18 位时间戳(闰秒等)的信息。我试图通过从 18 位信号(顶部显示的日期)创建已知日期字符串的 datenum 时间戳来获得差异。然后我在秒级上减去了两者。差值是 21427199.0218048

计算:

test=datenum('5-9-2012 17:42:01')% use date of 18 digit for datenum
test=test*24*3600                % convert to seconds
test-timestamp_18digits*10^(-7) 

现在的问题是,如果我将它添加到信号 2 datenum 时间戳并减去信号 1 18digit*10^-7 时间戳,我会得到 10281617.4543686 秒的巨大差异,而它应该是 7 小时 + 几秒。

计算: `

 ...; % Get Signal 1 and 2 timestamps

TS_signal2_s=timeStartCam*24*3600+7*3600; 
TS_signal2_s=TS_signal2_s+21427199.0218048; % adding the difference of the time stamps

offset_signals =TS_signal2_s-TS_signal1*(10^-7);%100ns`

有人提示我正在犯的错误吗?

我已经尝试了很多。任何帮助表示赞赏。 提前非常感谢。

附言我不能快速回答。请耐心等待。

【问题讨论】:

  • 我看到一个问题开始了:TS_signal1 存储的开头是什么?如果它存储为双精度,那么您从一开始就会遇到精度问题。正如here 所讨论的,double 可以可靠存储的最大整数是2^53,或者比9e15 多一点。 18 位时间戳不太可能准确表示(即,将有大量舍入到最接近的可表示整数值)。如果它以int64 或uint64 开头,那么你会很好。
  • 感谢您的建议。从现在开始,我会将其存储为 int64。虽然这应该不是问题,因为我只想要第二级(~9e10)的精度。

标签: .net matlab datetime timestamp data-conversion


【解决方案1】:

TL;DR,因为我在下面写得很详细...

TS_signal1 = int64(634824637219781900);  % .NET datetime number
TS_signal2 = 735117.446046926;           % MATLAB datetime number
ticks1 = System.DateTime(TS_signal1).AddYears(1).AddDays(2).Ticks;
ticks2 = int64(TS_signal2*1e9)*24*36;
dTicks = ticks1 - ticks2;          % Difference in ticks (100 nanoseconds)
dSeconds = double(dTicks)*(1e-7);  % Difference in seconds

dSeconds =
     2.518352378360000e+04  (just shy of 7 hours)

现在,解释...

我将分别处理每个日期时间的转换,并以一种尽可能保持精度的方式,即使您不一定需要它,因为您正在处理两个日期时间之间的差异小时顺序...

.NET DateTime

我立即注意到的一件事是,您的日期时间编号 (6.348246372197819e+17) 远大于 the maximum value a double-precision variable can reliably contain(2^53,或略大于 9e15)。并非高于该值的每个整数都可以精确表示,因此一旦开始存储大于双精度变量中的整数,您将开始看到由于四舍五入而导致的显着精度损失可表示的浮点数。

由于您将您的号码转换为int64,这让我相信您将其存储为之前的其他内容(如默认的double),而其他内容则不会这样做。您要确保从一开始就将其定义为 int64,如下所示:

TS_signal1 = int64(634824637219781900);

现在,比较 .NET 和 MATLAB datetimes(正如您所指出的)的一个关键问题是它们都在不同的参考时间点测量不同的量:自 1-JAN-0001 以来的滴答声(以 100 纳秒为单位)与分数自0-JAN-0000 以来的天数。我们需要考虑这种差异来比较这两个数字。一种方法是首先将时间添加到 .NET 日期时间,因为 MATLAB 日期时间有一个更早的参考时间,并且它相对于该时间的测量值要大得多。 p>

那么,我们应该增加多少时间?乍一看,只需减去参考时间(1-JAN-0001 减去 0-JAN-0000)就意味着我们将 .NET 日期时间添加 1 年零 1 天,以便它表示来自 0-JAN-0000 的滴答数。这很接近,但并不完全正确。由于0000 在技术上算作闰年,因此它有额外的一天,因此您实际上必须为 .NET 添加 1 年零 2 天 的额外刻度约会时间。我们可以用数学来做到这一点,或者我们可以使用System.DateTime 类和它的一些方法来让它变得快速和简单:

ticks1 = System.DateTime(TS_signal1).AddYears(1).AddDays(2).Ticks;

现在我们有了关于0-JAN-0000 的刻度数。我们可以将其转换为秒以继续我们的计算。但是,转换为秒需要将其更改为浮点表示(即double),这会导致精度损失,因为我们的数字仍然很大。最好以刻度为单位继续计算。

MATLAB serial date number

您的 MATLAB 日期时间,表示为日期序列号 (735117.446046926),是一个浮点值,用于测量自 0-JAN-0000 以来经过的(小数)天数。为了与我们的 .NET 日期时间进行比较,我们需要将其转换为刻度,因此我们应该将其缩放 24*3600*1e7(即小时/天乘以秒/小时乘以刻度/秒,刻度为 100 纳秒)。但是这里有一个问题。如果我们一次应用所有这些缩放,我们会再次用一个太大而无法处理的整数来压倒我们的double 变量,从而导致精度损失。但我们不想将double 转换为int64,直到我们将其放大到足以获得整数值,否则我们会冒着舍入小数信息的风险。

解决方案非常简单:应用尽可能多的缩放以获得仍然小于2^53 的大整数,转换为int64,然后应用缩放的剩余部分:

TS_signal2 = 735117.446046926;
ticks2 = int64(TS_signal2*1e9)*24*36;

把它们放在一起

我们现在可以计算两个时间点之间的滴答声(和秒数)的差异:

dTicks = ticks1 - ticks2;          % Difference in ticks (100 nanoseconds)
dSeconds = double(dTicks)*(1e-7);  % Difference in seconds

dSeconds =
     2.518352378360000e+04

为了确认,我们将其转换为hh:mm:ss duration 并与日期字符串进行比较:

durSec = seconds(dSeconds);  % Convert to a duration...
durSec.Format = 'hh:mm:ss'   % ... and format it

durSec = 
  duration
   06:59:43

System.DateTime(TS_signal1).ToString  % Convert .NET datetime to a string

ans = 
9/5/2012 5:42:01 PM

datetime(TS_signal2, 'ConvertFrom', 'datenum')  % Convert MATLAB datenum to a datetime

ans = 
  datetime
   05-Sep-2012 10:42:18

我们可以看到这两个时间实际上相差 6 小时 59 分 43 秒。我们可以将日期时间数字转换为日期字符串,然后提取小时、分钟和秒并进行一些数学运算以得到答案,但在此过程中我们会损失相当多的精度。像我们上面所做的那样以滴答为单位计算事物保持尽可能高的精度......

...保持所有可能的精度不是更好吗?

【讨论】:

  • 你是最棒的。谢谢你拯救了我的周末。今晚我会看看。现在我必须照顾我的家人。来自亚琛的问候
  • 亲爱的新手,再次非常感谢。我检查了它,当然,它运行起来就像一个魅力。你为我省去了一些持续的头痛。显然,我很接近,但我从未考虑过在刻度级别上合并它们。刚刚好。祝您一切顺利,并在您需要时得到您的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-12-30
  • 2012-07-09
  • 1970-01-01
  • 1970-01-01
  • 2016-02-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多