4

I have an annual time series where measurements are recorded at hourly intervals:

StartDate = '2011-01-01 00:00';
EndDate = '2011-12-031 23:00';
DateTime=datevec(datenum(StartDate,'yyyy-mm-dd HH:MM'):60/(60*24):...
    datenum(EndDate,'yyyy-mm-dd HH:MM'));
dat = 2+(20-2).*rand(size(DateTime,1),1);

I would like to calculate the mean 24 hour cycle for each week of the year i.e. for week 1, day of year 1 to 7 I want to calculate the average 00:00, 01:00,... and so on so eventually I will end up with 52, 24 hour series i.e. one for each week of the year. Matlab does have a function called 'weeknum' which returns the week number from a given seriel date number, however, this function is in the financial toolbox. Can anyone suggest an alternative method for finding week number?

HebeleHododo
  • 3,620
  • 1
  • 29
  • 38
KatyB
  • 3,920
  • 7
  • 42
  • 72
  • You might check out http://www.mathworks.de/matlabcentral/fileexchange/22663-weeknum – H.Muster Dec 18 '12 at 10:58
  • Thanks for the suggestion. Although I would prefer to use not use the FEX. I was hoping of finding a solution by using datevec to obtain the information on DateTime. – KatyB Dec 18 '12 at 11:37

4 Answers4

2

Maybe this can be of help (I'm using the current date and time as an example):

c = datevec(datestr(now));
week_num = ceil(diff(datenum([c(1), 1, 1, 0, 0, 0; c])) / 7)

I'm not sure how this solution handles edge cases properly, but I think it's a good place to start.

You can also verify it with this website that tells the current week number.

Applying this to your example can be done, for example, like so:

weeknum = @(v)ceil(diff(datenum([v(1), 1, 1, 0, 0, 0; v(:)'])) / 7);
arrayfun(@(n)weeknum(DateTime(n, :)), 1:size(DateTime, 1))'
Eitan T
  • 32,660
  • 14
  • 72
  • 109
1

According to Wikipedia, ISO week number is calculated like this.

I did it for today as an example.

offsetNotLeap = [0  31  59  90  120 151 181 212 243 273 304 334];
offsetLeap = [0 31  60  91  121 152 182 213 244 274 305 335];

todayVector = datevec(today);
todayNum = today;
ordinalDay = offsetLeap(todayVector(2)) + todayVector(3);
dayOfTheWeek = weekday(todayNum);
weekNumber = fix((ordinalDay - dayOfTheWeek + 10)/ 7)

weekNumber =

    51

I didn't do the checks for 0 and 53 cases. Also note that MATLAB's weekday function gives Sunday's index as 1, so if you want to make Monday's index 1, you need to do some adjustments. ISO says that Monday should be 1.

HebeleHododo
  • 3,620
  • 1
  • 29
  • 38
0

Just a simple weekday function with Monday as the first day of the week:

function [ daynumber,dayname ] = weekd( date )
%WEEKD Returns the day number and day name based on the input date
%   First day of week
%   -----------------
%   The first day of the week is Monday.
%
%   Parameter
%   ---------
%   date = Input date -> format: dd.mm.yyyy / Example: 21.11.2015

[dn,dayname] = weekday(datenum(date,'dd.mm.yyyy'));

if dn == 1;
   daynumber = 7;
elseif dn >= 2 && dn <= 7
   daynumber = dn - 1;
else      
   error('Invalid weekday number.'),
end

end
0

although some time has past since you posted your question, I want to give an additional answer, if people will have the same issue as me. As HebeleHododo already indicated, there exists a rule posted on Wikipedia how to compute the ISO week number. But anyhow, I wasn't able to find a generic code snippet for it.

Therefore, I developed the following generic method which is able to take vectors, matrices or single values of arbitrary datetimes with arbitrary reference years. Appreciate to read any constructive feedback. I successfully ran it on MATLAB R2017a and tested it further for some edge cases.

function week_num = get_week_num(dtimes)
    dnums   = datenum(dtimes);
    firsts  = datenum(year(dtimes), 1, 1);
    ordinal = floor(dnums - firsts);
    wday    = weekday(dtimes) - 1;

    wday(wday == 0) = 7;
    week_num = floor((ordinal + wday + 10) / 7);
end
fohletex
  • 96
  • 5
  • I am not sure if this is working as it should. `get_week_num(datetime(2023,1,1)` returns 2 for example. – Ken Jiiii Apr 14 '23 at 12:25