divide year time data into days and nights

6 views (last 30 days)
Hello,
I have a table of time data for entire year and I would like to divide them into days and nights. The table rows look like that (Time_begin Time_end other_variables), example of one row: (14-Mar-2017 12:10 14-Mar-2017 12:20 var1 var2 var3 ... ). I have a table of sunrises and sunsets (day_no sunrise sunset, Example: 1 01-Jan-2017 08:01:00 01-Jan-2017 16:10:00) for the entire year and I would like to use it for dividing the data table into tables with rows with day data and night data. The sunrise and sunset time change for every day. How can I do this? Thanks for you ideas.
  2 Comments
Petr Michalek
Petr Michalek on 22 Sep 2022
Lets say, that we use only the start time for the decision whether it is day or night. The timespan between start time and end time is always 10 minutes, so the difference is in order of minutes and that is small enough for me to cope with.

Sign in to comment.

Accepted Answer

Eric Sofen
Eric Sofen on 22 Sep 2022
Steve beat me to it, but here's another solution that uses the datetime isbetween function.
SunriseSunset = table((1:365)',datetime(2022,1,1:365,6,30,0)', datetime(2022,1,1:365,18,30,0)', VariableNames=["DoY", "Sunrise", "Sunset"]); % let's suppose sunrise and sunset don't change throughout the year
data = timetable(datetime(2022,1,1,0,0:90:10000,0)', rand(112,1), VariableNames="Data");
isday = isbetween(data.Time,SunriseSunset.Sunrise',SunriseSunset.Sunset');
% This takes advantage of implicit expansion and results in a big logical array
% of which particular day period the data's row time corresponds to. Just
% aggregate over rows to get a vector of which times are occuring during
% daytime.
data.isday = sum(isday,2)
data = 112×2 timetable
Time Data isday ____________________ _________ _____ 01-Jan-2022 00:00:00 0.48027 0 01-Jan-2022 01:30:00 0.43233 0 01-Jan-2022 03:00:00 0.086928 0 01-Jan-2022 04:30:00 0.37172 0 01-Jan-2022 06:00:00 0.55905 0 01-Jan-2022 07:30:00 0.94576 1 01-Jan-2022 09:00:00 0.39536 1 01-Jan-2022 10:30:00 0.54901 1 01-Jan-2022 12:00:00 0.83405 1 01-Jan-2022 13:30:00 0.22782 1 01-Jan-2022 15:00:00 0.25985 1 01-Jan-2022 16:30:00 0.0092988 1 01-Jan-2022 18:00:00 0.058855 1 01-Jan-2022 19:30:00 0.16832 0 01-Jan-2022 21:00:00 0.4819 0 01-Jan-2022 22:30:00 0.43895 0
  4 Comments
Eric Sofen
Eric Sofen on 23 Sep 2022
Presumably those NaTs are in your original data. Either missing timestamps or timestamps in a different format. Datetime can only parse one format at a time.
If you understand where the NaTs come from and just want to get rid of them, take a look at rmmissing.

Sign in to comment.

More Answers (1)

Steven Lord
Steven Lord on 22 Sep 2022
I'm going to use the sunrise and sunset times for Natick, MA for this example. I'll create some random datetime values for the next three days:
fmt = 'MMM dd, h:mm a';
threeDaysInMinutes = minutes(days(3));
data = datetime('today', 'Format', fmt) + minutes(randi([0 threeDaysInMinutes], 10, 1))
data = 10×1 datetime array
Sep 22, 4:01 AM Sep 24, 12:34 PM Sep 24, 10:25 AM Sep 22, 6:14 PM Sep 24, 6:21 AM Sep 23, 12:04 AM Sep 23, 4:29 AM Sep 24, 7:07 PM Sep 22, 1:15 AM Sep 24, 6:31 AM
Now I'll create the vector of sunset and sunrise values. Elements 1, 3, 5, etc. are sunset values and elements 2, 4, 6, etc. are sunrise values.
sunriseSunset = ["Sep 21, 2022 6:44 pm"; ...
"Sep 22, 2022 6:32 am"; "Sep 22, 2022 6:42 pm"; ...
"Sep 23, 2022 6:33 am"; "Sep 23, 2022 6:40 pm"; ...
"Sep 24, 2022 6:34 am"; "Sep 24, 2022 6:39 pm"; ...
"Sep 25, 2022 6:36 am"; "Sep 25, 2022 6:37 pm"; ...
"Sep 26, 2022 6:37 am"];
bins = datetime(sunriseSunset, 'Format', fmt)
bins = 10×1 datetime array
Sep 21, 6:44 PM Sep 22, 6:32 AM Sep 22, 6:42 PM Sep 23, 6:33 AM Sep 23, 6:40 PM Sep 24, 6:34 AM Sep 24, 6:39 PM Sep 25, 6:36 AM Sep 25, 6:37 PM Sep 26, 6:37 AM
By the way I constructed the sunriseSunset array, anything falling in odd numbered bins (bin 1 being between elements 1 and 2 of sunriseSunset, for example) is considered night and anything falling in even numbered bins is considered day.
whichBin = discretize(data, bins)
whichBin = 10×1
1 6 6 2 5 3 3 7 1 5
Let's look at the results in words rather than odd or even bin numbers. In each row, the value in the Dates variable falls after the value in the Begin variable and before the value in the End variable.
categories = categorical(["Night"; repmat(["Day"; "Night"], 4, 1)]); % Alternate Night and Day
result = table(data, bins(whichBin), bins(whichBin+1), categories(whichBin), ...
'VariableNames', ["Dates", "Begin", "End", "Day or Night"])
result = 10×4 table
Dates Begin End Day or Night ________________ _______________ _______________ ____________ Sep 22, 4:01 AM Sep 21, 6:44 PM Sep 22, 6:32 AM Night Sep 24, 12:34 PM Sep 24, 6:34 AM Sep 24, 6:39 PM Day Sep 24, 10:25 AM Sep 24, 6:34 AM Sep 24, 6:39 PM Day Sep 22, 6:14 PM Sep 22, 6:32 AM Sep 22, 6:42 PM Day Sep 24, 6:21 AM Sep 23, 6:40 PM Sep 24, 6:34 AM Night Sep 23, 12:04 AM Sep 22, 6:42 PM Sep 23, 6:33 AM Night Sep 23, 4:29 AM Sep 22, 6:42 PM Sep 23, 6:33 AM Night Sep 24, 7:07 PM Sep 24, 6:39 PM Sep 25, 6:36 AM Night Sep 22, 1:15 AM Sep 21, 6:44 PM Sep 22, 6:32 AM Night Sep 24, 6:31 AM Sep 23, 6:40 PM Sep 24, 6:34 AM Night

Categories

Find more on Timetables in Help Center and File Exchange

Products


Release

R2021b

Community Treasure Hunt

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

Start Hunting!

Translated by