-I wish to convert Matlab serial time (datenum, as in t_matlab=now
)
to c# Datetime (as in var t_cs = DateTime.Now.Ticks
).
Any idea how to do so?
[Edit] I found a way of doing it, but still not sure if it's the best way.
[Edit2] Fixed the wrong DateTimes, thanks Jonas!
function cstime = datenum2datetime( matlabSerialTime )
%Convert matlab serial time (datenum) to .net datenum.
%
% Example:
% ntTime = datenum2datetime(now)
% cstime = datenum2datetime([734539.4717013890 734539.5051388888]);
%
% See also datenum.
% using System.DateTime.Parse(string).Ticks to convert to DateTime format.
% t1 = now; t2 = now+1; matlab_times = [t1 t2];
% cs_times = [System.DateTime.Parse(datestr(t1)).Ticks ...
% System.DateTime.Parse(datestr(t2)).Ticks]
% aver = diff(cs_times)/diff(matlab_times);
% offver = cs_times(1) - matlab_times(1)*aver;
a = 10^7*60*60*24;
offset = -367*10^7*60*60*24;
cstime = a*matlabSerialTime + offset;
Edit: Surprised by jarr's answer I investigated further. Turns out that the example time points sharhar_m gives in the question are wrong (sorry for not checking that earlier).
In summary, the function given in the question is off by 367-281=86 days and should be corrected to
function cstime = datenum2datetime( matlabSerialTime )
cstime = 10^7*60*60*24*(matlabSerialTime - 367);
Now on to the details, in case anyone is interested: You claim
% {05-Feb-2011 11:19:15} in System.DateTime is 634399319550000000
but in MATLAB R2010b
sdt =System.DateTime(634399319550000000);
[sdt.Day sdt.Month]
returns [2 5]
, so your DateTime value is actually for May 2nd, not Feb 5th!! To calculate the correct values set
cs_times = [System.DateTime.Parse('05-Feb-2011 11:19:15').Ticks ...
System.DateTime.Parse('05-Feb-2011 12:07:24').Ticks]
which gives [634325015550000000 634325044440000000]
.
Time unit scaling
Your factor a
is 10^7*60*60*24 i.e. MATLAB stores the date/time in units "days" (with time as fractional days) and C# stores time as "ticks", i.e. number of "10^-7 seconds". You can probably avoid some rounding errors by putting in the precise value for a
.
Difference in reference time point
The offset b
expressed in days (b/a
) tells you that their "origin of time" is 367 days apart; with your old value for b
this came out to 281 days. The MATLAB documentation for datestr
states
"A serial date number represents the whole and fractional number of days from 1-Jan-0000 to a specific date. The year 0000 is merely a reference point and is not intended to be interpreted as a real year in time."
(even though running datestr(0,'dd-mm-yyyy HH-MM-SS')
reveals that the reference point is actually 0-Jan-0000). C# ticks are the
"number of 100-nanosecond intervals that have elapsed since 12:00:00 midnight, January 1, 0001, which represents DateTime.MinValue. It does not include the number of ticks that are attributable to leap seconds."
So in summary, the "origin in time" between both systems differs by one leap year and one day, hence 367 days. If you actually wanted to deal with real dates that far back, you would have to take the Gregorian calendar reform and Augustus' correction to the incorrect application of leap years in the Julian calendar before the year 8 into account... but I doubt this is of interest here ;-).
Use this to convert matlab serial date number to System.DateTime ticks:
function datetimeticks = mt2dt(matlabserialtime)
datetimeticks = (matlabserialtime - 367)*86400/1e-7;
end
And an example (in Matlab):
mdt = datenum('8/6/1901 07:50:13');
sdt = System.DateTime(mt2dt(mdt));
>> sdt.ToString
ans =
8/6/1901 07:50:13
The counterpart conversion from System.DateTime to Matlab serial date number is just as easy:
function matlabserialtime = dt2mt(datetimeticks)
matlabserialtime = double(datetimeticks) * 1e-7/86400 + 367;
end
And an example (in Matlab):
sdt = System.DateTime.Parse('8/6/1901 07:50:13');
mdt = datenum(dt2mt(sdt.Ticks));
>> datestr(mdt)
ans =
06-Aug-1901 07:50:13
Note, that you lose DateTimeKind info once converted to Matlab from DateTime ticks.
You may want to hold on to that and later use it with SpecifyKind or DateTime ctor.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With