Get the difference between two DateTimes with microsecond precision - date

In Elixir, you can use :calendar.datetime_to_gregorian_seconds/1 to convert an Erlang time into the number of seconds since Epoch. The problem is, just with the number of seconds, you can't differentiate between two events which happened in the same second.
The DateTime struct, which my dates are instances of, does store the microseconds component of the date, but doesn't give me an easy way to find the difference between two times.
Does anybody know of a way (preferably without the use of a library) to find the difference, in microseconds, between two DateTimes?

Pass the :microseconds option to DateTime.diff/3
iex(1)> x1 = DateTime.utc_now()
#DateTime<2018-02-17 06:27:33.291406Z>
iex(2)> x2 = DateTime.utc_now()
#DateTime<2018-02-17 06:27:39.692571Z>
iex(3)> DateTime.diff(x2, x1, :microseconds)
6401165

Related

Plotting multiple datasets in MATLAB

I have voltage and current signals from multiple days. The time vector is in seconds of the day (SOD), and the voltage and current vectors are in volts and amps respectively. However, the vector data from each day is different lengths. For example Mondays data might be 1x100000 for both time and voltage/current, and Tuesdays might be 1x50000 for both time and voltage/current. I was asked to plot the different days of data on the same figure for comparison purposes. I have tried using the plot(x1,y1,x2,y2) method but that obviously didn't work due to different vector lengths. I tried interpolating to the larger data set, but then realized that I will get all NaNs on the result since there is no overlap in time. I ran out of ideas and am desperately in need of help.
EDIT:
I guess I forgot to mention that somehow I would like to overlay them one on top of the other in the same figure and not using a subplot.
It sounds like you want a data vector of length n to span, I'm guessing, 24 hours = 86400 seconds, for any n (e.g. n=100000 or n=50000). Assuming the original data is uniformly sampled, this should do the trick:
x1=linspace(0,86400,length(x1));
x2=linspace(0,86400,length(x2));
plot(x1,y1,'r-',x2,y2,'b-');
If it is not uniformly sampled, we can still make it work:
t1=linspace(0,86400,length(x1));
t2=linspace(0,86400,length(x2));
newy1 = spline(x1,y1,t1);
newy2 = spline(x2,y2,t2);
plot(t1,newy1,'r-',t2,newy2,'b-');

SSRS 2008 Calculated Chart X-Axis Interval

I am trying to create a chart where the interval on the X-axis will redefine itself depending on the 2 time parameters I have set up for the report; I have a #StartTime and a #StopTime. If the difference between the dates is one day, I want the graph axis to show a mark at each whole hour during that day. But any more than a day then the interval can be automatically determined by the program.
I have manually set the difference between the 2 parameters to be 1 day and set the interval and interval type to "24" and "hours", respectively, which gives me the desired results.
I have tried the following function for the interval:
=IIf(DateDiff("d",Parameters!StartTime.Value,Parameters!StopTime.Value)=1, "24", "Auto")
And I have tried the following function for the interval type:
=IIf(DateDiff("d",Parameters!StartTime.Value,Parameters!StopTime.Value)=1, "Hours", "Auto")
I created 2 random textboxes into which I inserted these functions to test if the functions are actually working, and they are. So I can't figure out why the functions won't execute properly when inserted into the interval properties fields.
Why is this not displaying the desired outcome?
Instead of using the text "Auto", use a Nothing to represent Auto.
eg:
=IIf(DateDiff("d",Parameters!StartTime.Value,Parameters!StopTime.Value)=1, 24, Nothing)
If I recall correctly, you can't change the the axis type at render, which seems like what your trying to do. Honestly I think this might be a case for cheating, make the chart twice, one for each axis type you want, and then conditionally hide them based on a similar Iif statement to the ones you have above.
Other thoughts, 24 is not the interval you want, interval is how much of the x-axis is displayed as tic marks. 1 means 1 tic for every 1 value, 2 means every other one, and 24 if it works would be showing every 24th value (haven't tried it). You want a number interval with a type of hour and an interval of 1 because you want to show every hour. You'll also have to change your x axis to:
=datepart(hour, Fields!YourDateTime.Value)
Otherwise the numbers axis type won't work. You can use similar expressions to create day over day time comparisons. Anyway, good luck!

How to convert a MATLAB serial date number to a calendar date?

This is not so much a programming question as it is a desire for clarification to understand the way the Matlab serial date number format works. I'm referencing Matlab serial date numbers and I would like to know how to convert them into calendar dates using the simplest means possible. Many of the references out there only instruct how to work with these numbers within Matlab itself, but I want to be able to make sense of these by hand using arithmetic to derive the dates they represent without the use of Matlab (if this is even possible).
From the research I have done already, I do understand that a Matlab timestamp is essentially a count of the number of days since January 1, 0000 and that the floating point numbers appended to it further represent specific hours, minutes, etc. I'm not as clear on how these break down however. The reference information out there is not very informative nor comprehensive and I'm struggling to understand how it works.
Say I have the timestamp 735071.64930556. Could anybody provide me with a formula to be able to derive the calendar date that this represents, or guide me through the process to convert it? From a programming standpoint, my purpose for wanting to understand this is so I can eventually write a converter to be able to handle this format within the application I'm developing. For now though, I simply wish to understand how the process works.
Thanks
Use datevec or datestr:
>> datevec(735071.64930556)
ans =
1.0e+003 *
2.0120 0.0070 0.0210 0.0150 0.0350 0.0000
>> datestr(735071.64930556)
ans =
21-Jul-2012 15:35:00
What makes your question a little bit difficult to answer is mostly the leap year / leap second problem. If you expect date values to exist only over a limited range of values, the problem is somewhat simpler (actually I am not sure how Matlab deals with the "lost days" when the world went from Julian to Gregorian calendars, for example - see http://en.wikipedia.org/wiki/Conversion_between_Julian_and_Gregorian_calendars for a hint of what I am talking about).
The hours-minutes-seconds part is relatively easy. When you have
datevalue = 735071.64930556;
You can compute:
rem = datevalue - floor(datevalue);
hours = floor(24*rem);
rem = 24 * rem - hours;
minutes = floor( 60 * rem );
rem = 60 * rem - minutes;
seconds = 60 * rem;
To get the year / month / day, your best bet is to use some built in function in the language of your choice (for many examples, see http://www.epochconverter.com/epoch/daynumbers.php ), or knock yourself out and create some lookup tables. If you have the date of the first of every month, the lookup would be fast; and from 0 CE until today, that would be only 2013 * 12 entries - not a very large table. Such a table could be created in Matlab and exported...

Comparing dates and filling in gap times in matlab

I have a data file which contains time data. The list is quite long, 100,000+ points. There is data every 0.1 seconds, and the time stamps are so:
'2010-10-10 12:34:56'
'2010-10-10 12:34:56.1'
'2010-10-10 12:34:56.2'
'2010-10-10 12:34:53.3'
etc.
Not every 0.1 second interval is necessarily present. I need to check whether a 0.1 second interval is missing, then insert this missing time into the date vector. Comparing strings seems unnecessarily complicated. I tried comparing seconds since midnight:
date_nums=datevec(time_stamps);
secs_since_midnight=date_nums(:,4)*3600+date_nums(:,5)*60+date_nums(:,6);
comparison_secs=linspace(0,86400,864000);
res=(ismember(comparison_secs,secs_since_midnight)~=1);
However this approach doesn't work due to rounding errors. Both the seconds since midnight and the linspace of the seconds to compare it to never quite equal up (due to the tenth of a second resolution?). The intent is to later do an fft on the data associated with the time stamps, so I want as much uniform data as possible (the data associated with the missing intervals will be interpolated). I've considered blocking it into smaller chunks of time and just checking the small chunks one at a time, but I don't know if that's the best way to go about it. Thanks!
Multiply your numbers-of-seconds by 10 and round to the nearest integer before comparing against your range.
There may be more efficient ways to do this than ismember. (I don't know offhand how clever the implementation of ismember is, but if it's The Simplest Thing That Could Possibly Work then you'll be taking O(N^2) time that way.) For instance, you could use the timestamps that are actually present (as integer numbers of 0.1-second intervals) as indices into an array.
Since you're concerned with missing data records and not other timing issues such as a drifting time channel, you could check for missing records by converting the time values to seconds, doing a DIFF and finding those first differences that are greater than some tolerance. This would tell you the indices where the missing records should go. It's then up to you to do something about this. Remember, if you're going to use this list of indices to fill the gaps, process the list in descending index order since inserting the records will cause the index list to be unsynchronized with the data.
>> time_stamps = now:.1/86400:now+1; % Generate test data.
>> time_stamps(randi(length(time_stamps), 10, 1)) = []; % Remove 10 random records.
>> t = datenum(time_stamps); % Convert to date numbers.
>> t = 86400 * t; % Convert to seconds.
>> index = find(diff(t) > 1.999 * 0.1)' + 1 % Find missing records.
index =
30855
147905
338883
566331
566557
586423
642062
654682
733641
806963

How to use DateTime or FileTime date types in Matlab

I would like to parse/convert DateTime (or FileTime) data type which is int64 and measured in "ticks" which are 100-nanoseconds units, to a datenum or a better date & time format in Matlab.
I must use a counter with a high resolution 64bit as the difference between time stamps can be a couple of microseconds and the "spacing" isn't even.
Using latest Matlab version, the "ticks" variable is read as a string..
Any recommendations?
Thank you for your help
Datenums probably won't represent this effectively. They are doubles, an approximate type, with 1.0 = 1 day; the resolution limit for recent dates is about 10 microseconds. Also, the datenum related functions aren't written for high precision processing, and probably won't work well here.
>> datenum_precision = eps(now)
datenum_precision =
1.1642e-010
>> millisecond = 1.0/(24*60*60*1000)
millisecond =
1.1574e-008
>>
You're probably better off creating your own class that wraps the "ticks" as uint64 and provides methods for converting to human-readable presentation (like datestr()), doing addition and subtraction, parsing the strings you're getting to the uint64 values, and so on. Something with an interface like this.
classdef filetime
properties
tick; % An array of uint64 ticks
end
methods (Static = true)
out = parse(str); % Parse strings to #filetime
end
methods
out = filetimestr(obj); % human-readable strings
out = minus(a,b);
out = plus(a,b);
out = sort(obj);
out = datenum(obj); % maybe a lossy conversion to datenum, for convenience
end
end
You'll need R2010b to do arithmetic on 64-bit ints; older versions don't support it.
The tricky part would be if you wanted to do plots using the filetimetick objects; the Handle Graphics plots don't support user-defined objects.
You can convert your numbers to MATLAB's serial date with a simple equation:
step = 1e-7; % 100 nanosec
ticks = int64(250000);
timenum = double(ticks)*step/24/60/60;
First, for very large integer values converting to double might loose precision. If this is the case you probably better to stay with your numbers without converting to serial date.
Second, DATESTR/DATETICK functions support precision up to milliseconds. Try:
datestr(timenum,'HH:MM:SS.FFF')
So, think about it and please answer Andrew's comment - what do you need this conversion for?
D is a uint64 value of 100 ns since 01-01-1601, the result must be a datenum. This means days passed since 00-Jan-0000.
step = 100E-9; % 100 nanoseconds
step = step/(24*60*60); %fraction of a day
D = datenum('01-01-1601')+double(D)*step;
%D is now a datenum
Modern version using datetime (matlab >2014b)
%uint64 value of 100 ns since 01-01-1601
step = 100E-9; % 100 nanoseconds
step = step/(24*60*60); %fraction of a day
D = datetime('01-01-1601')+days(double(D)*step);
As mentioned above, both methods lose some of the accuracy that we had. In the case of datetimes this can probably be circumvented. It happens at double(D)*step because D is big for current dates. Many nanoseconds have passed since 1601. By converting D to a more recent offset one could get a more accurate conversion.