Generate timestamp series in Matlab? - matlab

all
I wonder if there is a way to generate timestamp series in Matlab ?
I assume there will be a start time, a end time, and a frequency.
It is simple to generate normal series using 1:1:100 (1 to 100 by 1)
How I can use a similar way to generate a time stamp series?
For instance, I specify start time as 9am, up to 10am, I want to generate something like 9:00:00:000, 9:00:00:500, 9:00:01:000, ....
gaped by 500 millisecond
Or even better, include date as well.

Use datenum, the only problem you might have is that your colliding with a gap second/day or summer savings time if you're spanning a long time period (but I don't think that's implemented in datestr as you can read here).
Play around with datenum, now and datestr
starttime = datenum(2000, 1, 1, 9, 0, 0);
dt = 0.500/86400; % datenum is a serial time format with 1 = 1 day = 86400 sec
N = 5;
timevec = starttime + dt*(0:(N-1));
>> datestr(timevec, 'HH:MM:SS.FFF')
ans =
09:00:00.000
09:00:00.500
09:00:01.000
09:00:01.500
09:00:02.000

Starting from 2015a, you can use the milliseconds function to build a vector of timesteps between to time points:
start = datetime('2017/1/3 9:00:00:000','InputFormat','yyyy/MM/dd H:mm:ss:SSS');
step = milliseconds(500);
fin = datetime('2017/1/3 10:00:00:000','InputFormat','yyyy/MM/dd H:mm:ss:SSS');
time_vec = start:step:fin;
If you don't define the date explicitly it will choose the current date.
You can also have one structure for both the time and the data, you can use the timeseries class (using start from above):
data = rand(7201,1);
ts = timeseries(data,'Name','MyTs');
ts.TimeInfo.StartDate = start;
ts.TimeInfo.Units = 'milliseconds';
ts = setuniformtime(ts,'Interval',500);
This will create a time series object:
>> ts
timeseries
Common Properties:
Name: 'MyTs'
Time: [7201x1 double]
TimeInfo: [1x1 tsdata.timemetadata]
Data: [7201x1 double]
DataInfo: [1x1 tsdata.datametadata]
with the following time info:
>> ts.TimeInfo
tsdata.timemetadata
Package: tsdata
Uniform Time:
Length 7201
Increment 500 milliseconds
Time Range:
Start 03-Jan-2017 09:00:00
End 03-Jan-2017 10:00:00
Common Properties:
Units: 'milliseconds'
Format: ''
StartDate: '03-Jan-2017 09:00:00'

It depends on your needs, but you can consider using the combination of datetime() and one or many of days(), hours(), minutes(), seconds() etc. functions.
Lets write some code:
start=datetime(1985,07,13,9,0,0); % your start date
steps=seconds(0:0.5:100); % your vector with steps
timeseries=start+steps; % your time series
you can also set format for displaying data that meets your needs, to do so check datetime properties manual.

Related

How can I stop Matlab rounding decimals when subtracting Datetime variables

I am having some issues in Matlab to do with rounding errors with datetime typed variables.
I have an array, lets call it 't', and it is of type datetime.
Say for example, t(2) = 00:01:35.6889999, and t(1) = 00:01:35.3549042.
If I try to do t(2)-t(1), all I get is an answer of type 'duration' of 00:00:00 .
I would like to find the difference between these times and keep the precision!
Any help, or directions to links that directly cater/relate to an issue like this would be appreciated! I'm not that familiar with using datetime & duration typed variables in Matlab!
Extra info: I am using Matlab R2017a
Edit: I have Format Long; written in my script.
Precision is not being lost, you just need to change the display format.
The default display format is HH:MM:SS:
>> A = duration(0, 0, 0, 1.25) % 1.25 MS
A =
duration
00:00:00
You can modify the format to display fractional parts. For example:
>> A.Format = 's' % Seconds only
A =
duration
0.00125 sec
>> A.Format = 'hh:mm:ss.SSSSSSSS' % HMS, up to 9 fractional second digits
A =
duration
00:00:00.00125000
You can also use helper functions like milliseconds or seconds to return double arrays:
>> seconds(A)
ans =
0.0013
>> milliseconds(A)
ans =
1.2500
This should work if only seconds vary in the two dates
second(t(1))-second(t(2))
The duration object actually has the proper precision. It just doesn't display it unless you set the format.
>> dur = duration(t(2) - t(1), 'Format', 's')
dur =
duration
0.3341 sec
Whether you set the format or not, you can grab the seconds directly from the duration object.
>> format long
>> seconds(dur)
ans =
0.334095700000000
>> seconds(t(2) - t(1))
ans =
0.334095700000000

clock Time on x-axis in matlab

I need some help related to plots in MATLAB.
I want to plot my data with respect to clock time on x-axis. I have an occupancy information data for every 15 minutes interval. I want to plot it against time. How can i do it? The problem is with the x-axis, how can i handle time and uniform intervals e.g data is of the form
data=[1 0 0 0 0 1 1 1 1 0 0 0 .............]
value of time is from 9 AM to 9 PM and the interval is 15 minutes
How can i set the intervals on the x-axis?
Thank you
The following code solves the problem. you enter Integer values for starting hour and minute, the ending time and the time steps between the measurements. Further enter/change the steps_x value. This shows how many time values are skipped on the x-axis. 7=skip6 values. Below the for-loop is my y-data. I just used random-function.
The resulting x-axis is a cell-array. This could be a problem for some applications. Further I used some 'unneccessary' variables. These i used for verifing my code. I didn't change it, because i thought that it would be easier to understand that way.
The biggest problem of my so
clc; clear all; close all;
%%//Variable declaration
start_hour = 9; %in hours
start_min = 5; %//in minutes
steps_min = 10; %//in minutes
end_hour = 21.0; %//in hours
end_min= 0; %//in minutes
steps_x = 7; %//how many times are displayed on the axis, doesn't change data
%%// code for computing internal values, steps and transforming to am/pm
%//changes the entries above to hour display(9.75=9h45min)
start_time= (start_hour+start_min/60);
%//changes the entries above to hour display(9.75=9h45min)
end_time=(end_hour+end_min/60);
%//changes steps to hour
steps_hour= steps_min/60;
%//array of hours
mytest_timeline = start_time:steps_hour:end_time;
%//array of minutes(copied and modified from #natan)
mytest_minutes = mod((0:steps_min:(steps_min*(length(mytest_timeline)-1)))+start_min,60);
%//cell array for am/pm display
mytest_timeline_ampm = num2cell(mytest_timeline);
%//if hour is smaller 12 write am otherwise pm
for k=1:length(mytest_timeline);
if mytest_timeline(k) < 12
mytest_ampm = {'am'};
%//converting the down rounded hour to str
helper_hour=num2str(mod(floor(mytest_timeline(k)),12));
%//converting the minute to str and giving it 2 digits eg. 05 for 5min
helper_minute = num2str(mytest_minutes(k),'%02d');
%//joining strings
mytest_timeline_ampm(k)= strcat(helper_hour,{'.'}, helper_minute, mytest_ampm);
%//same as for am just for pm
else
mytest_ampm = {'pm'};
helper_hour=num2str(mod(floor(mytest_timeline(k)),12));
helper_minute = num2str(mytest_minutes(k),'%02d');
mytest_timeline_ampm(k)= strcat(helper_hour,{'.'}, helper_minute, mytest_ampm);
end
end
%%// generated y data so that i could test the code
mytest_y = rand(size(mytest_timeline));
%%// changing display
%//x-coordinates(for displaying x,y)
mytest_x= 1:length(mytest_timeline);
%//x-axis label
mytest_x_axis = 1:steps_x:length(mytest_timeline);
%//plots the data mytest_y in uniform distances (mytest_x)
plot(mytest_x, mytest_y, 'b')
%//changes the x-label accordingly to mytest_x_axis to the am/pm timeline
set(gca, 'XTick',mytest_x_axis, 'XTickLabel',mytest_timeline_ampm(mytest_x_axis))

Error in data source: correct iteratively the vector without for loop?

Hello everyone I have a new small problem:
The data I am using have a weird trade time that goes from 17.00 of one day to 16.15 of the day after.
That means that, e.g., for the day 09-27-2013 The source I am using registers the transactions occurred as follows:
DATE , TIME , PRICE
09/27/2013,17:19:42,3225.00,1 #%first obs of the vector
09/27/2013,18:37:59,3225.00,1 #%second obs of the vector
09/27/2013,08:31:32,3200.00,1
09/27/2013,08:36:17,3203.00,1
09/27/2013,09:21:34,3210.50,1 #%fifth obs of the vector
Now first and second obs are incorrect for me: they belong to 9/27 trading day but they have been executed on 9/26. Since I am working on some functions in matlab that relies on non-decremental times I need to solve this issue. The date format I am using is actually the datenum Matlab format so I am trying to solve the problem just subtracting one from the incorrect observations:
%#Call time the time vector, I can identify the 'incorrect' observations
idx=find(diff(time)<0);
time(idx)=time(idx)-1;
It is easy to tell that this will only fix the 'last' incorrect observations of a series. In the previous example this would only correct the second element. And I should run the code several times (I thought about a while loop) until idx will be empty. This is not a big issue when working with small series but I have up to 20millions observations and probably hundred of thousands consecutively incorrect ones.
Is there a way to fix this in a vectorized way?
idx=find(diff(time)<0);
while idx
However, given that the computation would not be so complex I thought that a for loop could efficiently solve the issue and my idea was the following:
[N]=size(time,1);
for i=N:-1:1
if diff(time(i,:)<0)
time(i,:)=time(i,:)-1;
end
end
sadly it does not seems to work.
Here is an example of data I am actually using.
735504.591157407
735507.708030093 %# I made this up to give you an example of two consecutively wrong observations
735507.708564815 %# This is an incorrect observation
735507.160138889
735507.185358796
735507.356562500
Thanks everyone in advance
Sensible version -
for count = 1:numel(time)
dtime = diff([0 ;time]);
ind1 = find(dtime<0,1,'last')-1;
time(ind1) = time(ind1)-1;
end
Faster-but-crazier version -
dtime = diff([0 ;time]);
for count = 1:numel(time)
ind1 = find(dtime<0,1,'last')-1;
time(ind1) = time(ind1)-1;
dtime(ind1+1) = 0;
dtime(ind1) = dtime(ind1)-1;
end
More Crazier version -
dtime = diff([0 ;time]);
ind1 = numel(dtime);
for count = 1:numel(time)
ind1 = find(dtime(1:ind1)<0,1,'last')-1;
time(ind1) = time(ind1)-1;
dtime(ind1) = dtime(ind1)-1;
end
Some average computation runtimes for these versions with various datasizes -
Datasize 1: 3432 elements
Version 1 - 0.069 sec
Version 2 - 0.042 sec
Version 3 - 0.034 sec
Datasize 2: 20 Million elements
Version 1 - 37029 sec
Version 2 - 23303 sec
Version 3 - 20040 sec
So apparently I had 3 other different problems in the data source that I think could have stucked the routine Divakar proposed. Anyway I thought it was being too slow so I started thinking to another solution and came up with a super quick vectorized one.
Given that the observations I wanted to modify fall in a determined known interval of time the function just look for every observation falling in that interval and modifies it as I want (-1 in my case).
function [ datetime ] = correct_date( datetime,starttime, endtime)
%#datetime is my vector of dates and times in matlab numerical format
%#starttime is the starting hour of the interval expressed in datestr format. e.g. '17:00:00'
%#endtime is the ending hour of the interval expressed in datestr format. e.g. '23:59:59'
if (nargin < 1) || (nargin > 3),
error('Requires 1 to 3 input arguments.')
end
% default values
if nargin == 1,
starttime='17:00';
endtime='23:59:59';
elseif nargin == 2,
endtime='23:59:59';
end
tvec=[datenum(starttime) datenum(endtime)];
tvec=tvec-floor(tvec); %#As I am working on multiples days I need to isolate only HH:MM:SS for my interval limits
temp=datetime-floor(datetime); %#same motivation as in the previous line
idx=find(temp>=tvec(1)&temp<=tvec(2)); %#logical find the indices
datetime(idx)=datetime(idx)-1; %#modify them as I want
clear tvec temp idx
end

display clock time from decimal time in matlab

I have this code as part of my program to calculate the solar time. But my calculation using decimal time. And now, I need to display the result in clock time.
%To calculate solar time
stime = time + (((4*(Lloc-Lsm))+ Et)/60);
disp(['The true solar time is ' num2str(stime),'hr']); %To display the solar time
The answer goes like this:
The true solar time is 13.0501hr
How can I convert the time to clock time (12hr or 24 hr format). i.e the minute should multiply by 60 (0.0501*60min = 3.006) and the time should display as 13:03 or 1:03PM.
Appreciate your help. Thank you.
Regards, -researcher-
you can use the following
my_hour = floor(stime);
my_minute = round(mod(stime, 1) * 60);
disp(['The true solar time is ', num2str(my_hour), ':', num2str(my_minute)]);
Use datenum to convert to a serial date number and then datestr to build the string with appropriate format:
h = 13.0501; %// your computed decimal time
string = datestr(datenum([0 0 0 h 0 0]),14); %// or change "14" for other formats
The two formats you specify correspond to formats 13 through 16 in datestr (see link to the documentation above). For example, with format 14 the string is
>> disp(string)
1:03:00 PM

Matlab: time series plot for 44100 hz data

I'm trying to plot a time series which has been collected at a rate of 44100 hz. I would like to have the time (in seconds) and possibly the date on the x-axis.
Say I have data for one minute, i.e. 2646001 data points and assume, for simplicity, all data points are ones:
y=repmat(1,2646001,1);
I created a vector of date numbers by converting the start and end date into serial date numbers and then create a vector from the first time number to the last time number with rate 44100 hz:
StartTimeNum = datenum(2013,11,12,23,00,0);
EndTimeNum = datenum(2013,11,12,23,01,0);
T = EndTimeNum-StartTimeNum;
TimeNum = StartTimeNum:(T/length(y)):EndTimeNum;
I then define the format I would like the date string to be in and convert the time number vector into time string.
FormatOut = 'dd/mm/yy, HH:MM:SS.FFF';
TimeStr= datestr(TimeNum, FormatOut);
but now TimeStr is a <2646001x22 char>, rather than a <2646001x1 char> which Matlab doesn't allow me to use as the input for the x-axis.
In another attempt I found the timeseries class (http://www.mathworks.co.uk/help/matlab/ref/timeseries.plot.html) which would be perfect, but because my data is in 44100 hz, I am not sure how to define the units (ts1.TimeInfo.Units), which are generally described as 'days', or 'hours' or 'seconds' but not in hz...
Is there any way around this?
Thanks
y=ones(2646001,1); % use ones(m,n) for more efficiency
StartTimeNum = datenum(2013,11,12,23,00,0);
EndTimeNum = datenum(2013,11,12,23,01,0);
T = EndTimeNum-StartTimeNum;
TimeNum = StartTimeNum:(T/(length(y)-1)):EndTimeNum; % length consistent
FormatOut = 'dd/mm/yy, HH:MM:SS.FFF';
figure,plot(TimeNum, y),datetick('x',FormatOut)
Plot your data vs. TimeNum directly, then use datetick to set the labels:
plot(TimeNum, y);
datetick('x', 'dd/mm/yy, HH:MM:SS.FFF');
Or try just datetick with no arguments. The default format might be better.