add 'dd-MMM-yyyy' data to datetime array in form 'HH:mm:ss:SSS' with rollover

10 views (last 30 days)
I need to add calendar date information to an array of datetime data in the form 'HH:mm:ss:SSS', i have the date that the data starts being collected on and a snippet of the data looks like this
'23:59:59:873'
'23:59:59:893'
'23:59:59:933'
'23:59:59:963'
'00:00:00:003'
'00:00:00:043'
'00:00:00:073'
'00:00:00:103'
I know how to reformat the datetime data so it includes the calendar information and assign a year month and day to the data with
TimeData.Format = 'dd-MMM-yyyy HH:mm:ss:SSS';
TimeData.Year = startTime.Year;
TimeData.Month = startTime.Month;
TimeData.Day = startTime.Day;
This makes the data look like
'04-Jan-2023 23:59:59:873'
'04-Jan-2023 23:59:59:893'
'04-Jan-2023 23:59:59:933'
'04-Jan-2023 23:59:59:963'
'04-Jan-2023 00:00:00:003'
'04-Jan-2023 00:00:00:043'
'04-Jan-2023 00:00:00:073'
'04-Jan-2023 00:00:00:103'
Im wondering how to go about providing the TimeData array a start date, and have it update the date as the data rolls over 24 hours to a new day, having the data look like this
'04-Jan-2023 23:59:59:873'
'04-Jan-2023 23:59:59:893'
'04-Jan-2023 23:59:59:933'
'04-Jan-2023 23:59:59:963'
'05-Jan-2023 00:00:00:003'
'05-Jan-2023 00:00:00:043'
'05-Jan-2023 00:00:00:073'
'05-Jan-2023 00:00:00:103'

Accepted Answer

Star Strider
Star Strider on 11 Jan 2023
Edited: Star Strider on 12 Jan 2023
I’m not certain how robust this is, however it seems to work in this example —
Times = ['23:59:59:873'
'23:59:59:893'
'23:59:59:933'
'23:59:59:963'
'00:00:00:003'
'00:00:00:043'
'00:00:00:073'
'00:00:00:103'];
Time = datetime([Times; Times; Times], 'InputFormat','HH:mm:ss:SSS'); % Repeat To Test Code
DI = cumsum([0; diff(hour(Time))<0]); % Day Increment
Date = datetime('04-Jan-2023') + days(DI); % 'Date' Vector
DateTime = Date + timeofday(Time); % Date + Time
DateTime.Format = 'dd-MMM-yyyy HH:mm:ss.SSS'
DateTime = 24×1 datetime array
04-Jan-2023 23:59:59.873 04-Jan-2023 23:59:59.893 04-Jan-2023 23:59:59.933 04-Jan-2023 23:59:59.963 05-Jan-2023 00:00:00.003 05-Jan-2023 00:00:00.043 05-Jan-2023 00:00:00.073 05-Jan-2023 00:00:00.103 05-Jan-2023 23:59:59.873 05-Jan-2023 23:59:59.893 05-Jan-2023 23:59:59.933 05-Jan-2023 23:59:59.963 06-Jan-2023 00:00:00.003 06-Jan-2023 00:00:00.043 06-Jan-2023 00:00:00.073 06-Jan-2023 00:00:00.103 06-Jan-2023 23:59:59.873 06-Jan-2023 23:59:59.893 06-Jan-2023 23:59:59.933 06-Jan-2023 23:59:59.963 07-Jan-2023 00:00:00.003 07-Jan-2023 00:00:00.043 07-Jan-2023 00:00:00.073 07-Jan-2023 00:00:00.103
It works by creating the ‘DI’ (‘Day Increment’) vector, and adding it appropriately to the successive days. Try it on your complete data set to see if it gives the desired result.
EDIT — (12 Jan 2023 at 00:36)
Changed ‘~=0’ to ‘<0’ in the ‘DI’ calculation.
.
  4 Comments
dpb
dpb on 11 Jan 2023
Times = ['23:59:59:873'
'23:59:59:893'
'23:59:59:933'
'23:59:59:963'
'00:00:00:003'
'00:00:00:043'
'00:00:00:073'
'00:00:00:103'];
Time = datetime(Times,'InputFormat','HH:mm:ss:SSS');
Time=[Time;Time(5:end)+hours(1);]; % add an hour turnover besides day
Time=repmat(Time,2,1); % and another copy to test
DI = cumsum([0; diff(hour(Time))~=0]); % Day Increment
Date = datetime('04-Jan-2023') + days(DI); % 'Date' Vector
DateTime = Date + timeofday(Time); % Date + Time
DateTime.Format = 'dd-MMM-yyyy HH:mm:ss.SSS'
DateTime = 24×1 datetime array
04-Jan-2023 23:59:59.873 04-Jan-2023 23:59:59.893 04-Jan-2023 23:59:59.933 04-Jan-2023 23:59:59.963 05-Jan-2023 00:00:00.003 05-Jan-2023 00:00:00.043 05-Jan-2023 00:00:00.073 05-Jan-2023 00:00:00.103 06-Jan-2023 01:00:00.003 06-Jan-2023 01:00:00.043 06-Jan-2023 01:00:00.073 06-Jan-2023 01:00:00.103 07-Jan-2023 23:59:59.873 07-Jan-2023 23:59:59.893 07-Jan-2023 23:59:59.933 07-Jan-2023 23:59:59.963 08-Jan-2023 00:00:00.003 08-Jan-2023 00:00:00.043 08-Jan-2023 00:00:00.073 08-Jan-2023 00:00:00.103 09-Jan-2023 01:00:00.003 09-Jan-2023 01:00:00.043 09-Jan-2023 01:00:00.073 09-Jan-2023 01:00:00.103
What afraid of, @Star Strider, the test for ~0 turns over a day for every hour change, not just rollover at midnight...
Star Strider
Star Strider on 11 Jan 2023
Edited: Star Strider on 12 Jan 2023
@Leo Rogers — My pleasure!
The ‘DI’ vector is set to increment only when there is an abrupt negative change in the hours difference. It shouldn’t increment in any othe condition, providing the hours are always in a 24-hour cycle. A 12-hour cycle with AM and PM would break it, and I would need to figure out a way to deal with that.
Note added in proof —
v = linspace(0, 23, 4).'*ones(1,5);
v = v(:).';
DI = cumsum([0 diff(v)<0]);
A = [fix(v); DI]
A = 2×20
0 7 15 23 0 7 15 23 0 7 15 23 0 7 15 23 0 7 15 23 0 0 0 0 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4
EDIT — (12 Jan 2023 00:40)
Added example.
.

Sign in to comment.

More Answers (2)

dpb
dpb on 11 Jan 2023
Edited: dpb on 11 Jan 2023
Let's try a little mod on @Star Strider's idea...
Times = ['23:59:59:873'
'23:59:59:893'
'23:59:59:933'
'23:59:59:963'
'00:00:00:003'
'00:00:00:043'
'00:00:00:073'
'00:00:00:103'];
Time = datetime(Times,'InputFormat','HH:mm:ss:SSS');
Time=[Time;Time(5:end)+hours(1);]; % add an hour turnover besides day
Time=repmat(Time,2,1); % and another copy to test
DI = cumsum([0; diff(hour(Time))<0]); % Day Increment
Date = datetime('04-Jan-2023') + days(DI); % 'Date' Vector
DateTime = Date + timeofday(Time); % Date + Time
DateTime.Format = 'dd-MMM-yyyy HH:mm:ss.SSS'
DateTime = 24×1 datetime array
04-Jan-2023 23:59:59.873 04-Jan-2023 23:59:59.893 04-Jan-2023 23:59:59.933 04-Jan-2023 23:59:59.963 05-Jan-2023 00:00:00.003 05-Jan-2023 00:00:00.043 05-Jan-2023 00:00:00.073 05-Jan-2023 00:00:00.103 05-Jan-2023 01:00:00.003 05-Jan-2023 01:00:00.043 05-Jan-2023 01:00:00.073 05-Jan-2023 01:00:00.103 05-Jan-2023 23:59:59.873 05-Jan-2023 23:59:59.893 05-Jan-2023 23:59:59.933 05-Jan-2023 23:59:59.963 06-Jan-2023 00:00:00.003 06-Jan-2023 00:00:00.043 06-Jan-2023 00:00:00.073 06-Jan-2023 00:00:00.103 06-Jan-2023 01:00:00.003 06-Jan-2023 01:00:00.043 06-Jan-2023 01:00:00.073 06-Jan-2023 01:00:00.103
OK, at least a first blush it appears that simply checking to be sure the hour rollover is <0 will work; again the caveat about dealing with DST.
I've always wondered why TMW didn't introduce some tools with the timetable or just with datetime class to help with the rollover issues -- I've found several times that the rollover bug bit and no real help available to deal with it at higher level. I can't think of the specific examples at the moment, unfortunately, but I do recall having had difficulties...

Leo Rogers
Leo Rogers on 12 Jan 2023
Thank you both, totally works, i was worried it might take a while to crunch theres alot of data. But works perfect. Ya i think its odd matlab doesnt have anything prebuilt for something like this. It'd be handy to just have a built in function to provide a start date and datetime or duration array and have it just add the dates to it. I feel like thats a situation that comes up enough its warented. Anyway, your solutions as a function
% provide Times as array of datetime data, and startDate as a datetime
% data object at the desired start date, returns datetime data with date
% information
function dateTimes = dateTimeArray(Times, startDate)
DI = cumsum([0; diff(hour(Times))<0]);
Y = startDate.Year;
M = startDate.Month;
D = startDate.Day;
dates = datetime(Y,M,D) + days(DI);
dateTimes = dates + timeofday(Times);
dateTimes.Format = 'dd-MMM-yyyy HH:mm:ss.SSS';
end
Thanks again!
  11 Comments
youma
youma on 12 Apr 2023
You're a life saver, you know that?
So yes, you rcomment made me wonder, cause I had a timetable in the beginning but while working with meteo_data I had to put it into this format'yyyy-mm-dd HH:MM:SS' at some point so I used "datestr", and forgot that I even used it.
Thanks again, it worked!!

Sign in to comment.

Categories

Find more on Timetables in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!