find in array of datetimes - matlab

I have two excel files with dates in each of them. The goal is to find the location of datetimes in file A in file B.
e.g.
Excel file A has dates and each hour in column A from 1Jan1970 1AM to 31Dec2015 1AM with a lot of random missing dates and hour.
Excel file B has date e.g. 1jan1978 5PM
I read file A in array called A and do the following:
ind = find( x2mdate(A) == x2mdate(28491.7083333333) ); %datestr(x2mdate(28491.7083333333)) ans = 01-Jan-1978 17:00:00
it returns empty even though I can see that 1/1/1978 all hours are available in file A.
This is clearly a rounding issue. So, how do I deal with this? I tried using datestr but it is very slow.

Instead of x2mdate(28491.7083333333), try using:
datenum('01-Jan-1978 17:00:00', 'dd-mmm-yyyy HH:MM:SS')
It's easy to see that because of the rounding, they are not considered equal:
>> datenum('01-Jan-1978 17:00:00', 'dd-mmm-yyyy HH:MM:SS') == x2mdate(28491.7083333333)
ans =
0

You are comparing to the wrong value. 28491.7083333333 is slightly off the value you are looking for. When you want to use a precise match with constant floats, you have to use 17 digits. Otherwise compare with a reasonable tolerance.
tol=datenum(0,0,0,0,0,60) %60 seconds tolerance
ind = find( abs(x2mdate(A) - x2mdate(28491.7083333333)<tol );

Related

Is there an easy way to read integer time data from a netcdf file using the time-attribute?

I am trying to read time-coordinate data from a netCDF file using matlab. I have a netCDF file (which I created) that has a time variable in the format of a double corresponding to the number of hours from a specific time (see below).
Variable attributes:
double time(Time) ;
time:standard_name = "Time" ;
time:units = "hours since 2002-01-01 0:0:0" ;
time:calendar = "proleptic_gregorian" ;
When I read the time variable using ncread) into matlab, it just prints out an integer e.g.,1. However, if I use "ncdump" to explore the file, I see the time variable in it's coordinate time e.g., 2002-01-01 01.
Specifically: "ncdump -t -v time ncfile.nc"
I'm relatively new to matlab, and I was wondering if anyone knew if there was a similar, or an equally simple, way to read this time variable as its coordinate time into matlab, either as a string, or numerical date. Specifically, I would like to avoid having to parse the attribute string and code up a bunch of pointers and conditions to convert the integer data to an actual date.
Alternatively, should I just create a new time variable in these files that is just an array of dates as strings?
Any information is very much appreciated!
Thanks!
NetCDF stores time as an offset from an epoch. From your variable attribute, your epoch is 2002-01-01 0:0:0, and the time is hours since then. Matlab has a similar methodology called date numbers, although it is based off of days since an epoch (which they call pivot years). There are two functions that you should look into: datenum and datestr. The first converts a string into a date number and the other converts a date number into a date string.
You can convert your time variable into a compatible Matlab date number by dividing by 24 and then use the datestr function to format it however you like. Here is a simple example:
>> time = [1;2;3;4];
>> datestr(time./24+datenum('2002-01-01 0:0:0'))
ans =
01-Jan-2002 01:00:00
01-Jan-2002 02:00:00
01-Jan-2002 03:00:00
01-Jan-2002 04:00:00
Look at the Matlab help files associated with the two functions and you can format the date output however you like.

Convert cell to date in matlab using datenum?

I have a matrix containing the date in a cell structure. I managed to convert the date (2nd column) using datenum(), but I am not sure how to add on the time (3rd column)
The data looks like this:
'IBM' 20090602 0 108.410000000000
'IBM' 20090602 500 108.560000000000
My code:
date = datenum(num2str(IBM(:,2)),'yyyymmdd')
Let's review your mistakes first:
You feed datenum with the string 'IBM(:, 2)' instead of the actual array. Discard the quotes.
datenum accepts strings, not numerical values.
A possible solution is converting the second column of your data into an array of strings, and feeding it into datenum, like so:
d = datenum(num2str(vertcat(IBM{:, 2})), 'yyyymmdd');
Note that this is, of course, possible only if the format of the date string is fixed in each row.
EDIT:
To add the values in the third column to the result of datenum, simply do the following:
d + vertcat(IBM{:, 3})
Where d is a column vector of date values obtained from datenum (I assume that you want to do basic addition, since you haven't specified the actual meaning of the timje values in the third column).
In one line, the complete answer would look like this:
datenum(num2str(vertcat(IBM{:, 2})), 'yyyymmdd') + vertcat(IBM{:, 3})
You can straight-up add the time values in when you're converting to datenum. Just convert from what I assumed were minutes (if they're in seconds, add in another *60 to the divisor) to days, which is what MATLAB uses for its datenum calculations.
timestamps = cellfun(#(x,y) datenum(num2str(x),'yyyymmdd')+y/(24*60),...
IBM(:,2),...
IBM(:,3),...
'UniformOutput',false)

datetime format in matlab

I have some data that was given to me in excel and the time format is rather confusing. The fist column of the is the DateTime but with incorrect HH:MM and the second column is the correct hour of the day HH:MM:
time = {'01/01/2000 00:00',num2str(2300);
'01/01/2000 00:00',num2str(2400);
'01/01/2000 00:00',num2str(10);
'01/01/2000 00:00',num2str(100)};
However, when the time exceeds midnight, instead of being 00:10 the time is 10, and 01:00 is 100. How could I alter these to the correct format? i.e. from the example above I would like the outcome to be:
time = {'01/01/2000 23:00';
'01/01/2000 24:00';
'01/01/2000 00:10';
'01/01/2000 01:00'};
How could I achieve this?
Using sprintf in MATLAB, you can use the field width specifier:
where
Field width:
Minimum number of characters to print. Can be a number, or an asterisk (*) to refer to an argument in the input list. For example, the input list ('%12d', intmax) is equivalent to ('%*d', 12, intmax).
Thus your times should end up all looking like "XX:XX", with the leading zero added by the sprintf if it is missing and the colon added in.
Thanks to #Junuxx for the exact command: sprintf('%02i:%02i', hours, minutes)
To separate hours and minutes, you would obviously do time % 100 to get the minutes and integer divide by 100 to get the hours.
From there, you simply strcat or concatenate ["a" "b"] your two columns to get your desired result.

MATLAB - working with timestamps

How can I convert this kind of data 08:00:43.771 given as string into a number specifying the number of milliseconds since midnight corresponding to this time instance?
I generally use the Matlab datenum outputs for timestamping in Matlab. Datenums are the number of days since 0/0/0000, expressed as a double (double precision numbers are precise to about 14 usec for contemporary dates).
Using datenums.
currentDateTime1 = datenum('08:00:43.771'); %Assumes today
currentDateTime2 = datenum('6/8/1975 08:00:43.771'); %Using an explicit date
millisecondsSinceMidnight = mod(currentDateTime1 ,1) *24*60*60*1000; %Mod 1 removes any day component
millisecondsSinceMidnight = mod(currentDateTime2 ,1) *24*60*60*1000; %Then this is just a unit conversion
For unusual string formats, use the extended form of datenum, which can accept a string format specifier.
Use 1000*etime(datevec('08:00:43.771'),datevec('0:00')) to give the number of milliseconds since midnight. etime gives the number of seconds between two date vectors, datevec converts strings to date vectors (assuming Jan 1 this year if only a time is given).

How can i interpret a time value in ascii into a numerical value?

I have a file which is as follows:
15:03:21 II 0.88 0.64
15:03:31 II 0.88 0.64
15:03:42 II 0.40 0.40
etc.
after loading the file in matlab, I want to be able to read the first column (which corresponds to time) and interpret them as numerical values. At the moment, they are interpreted as a string of ascii characters and i can't perform any mathematical operations on them. Does anyone have any suggestions as to how i can read the time as numbers instead of a string of ascii characters?
Use DATENUM and DATEVEC to convert your date strings to useful numeric values.
Like Jonas said, but more specifically,
t = {'15:03:21 ' '15:03:31 ' '15:03:42 '};
datenum(t, 'HH:MM:SS')
In addition to above answers there is another useful function DATEVEC which converts either date string or datenum output to vector of year-month-day-hours-minutes-seconds. Try it out:
tvec = datevec(t)
Notice that if there is only time in the string, the date will be January 1st of the current year. You can always cut it out with
tvec(:,1:3) = [];