File Exchange

image thumbnail

Round off dates and times

version 1.1 (5.99 KB) by

Rounds off a datenum to the nearest second, minute, hour, day, month or year.

16 Downloads

Updated

View License

Rounds off a datenum to the nearest second, minute, hour, day, month or year. Zip file includes "units.m" (file 4093) by Henning Ressing.

Example: datenum_round_off(now, 'minute')

Comments and Ratings (6)

Kai Parker

I had a bit of a problem with this function as it introduced a slight rounding error in floating point notation in comparison to the datenum command. This causes a failure when using intersect. Solved by adding:

% Deal with rounding issues by converting to a datevector then back to a
% datenumber;
temp = datevec(datenum_rounded);
datenum_rounded = datenum(temp);

Chad Greene

Chad Greene (view profile)

This solved my problem perfectly, right out of the box. Thanks for sharing.

Matlab2010

with the below mod:

function datenum_rounded = datenum_round_off(datenum_in, time_unit_string, direction)
% Rounds off a datenum to the nearest second, minute, hour, whatever.
%
% datenum_rounded = datenum_round_off(datenum_in, time_unit_string)
%
% Inputs:
% datenum_in Date/time in Matlab datenum format
% time_unit_string String like 'minute', 'second', etc.
%
% Output:
% datenum_rounded Input value rounded off

% Kevin J. Delaney
% January 13, 2010
if(nargin<3)
    direction = 'default';
end

datenum_rounded = [];

if ~exist('datenum_in', 'var')
    help(mfilename);
    return
end

if isempty(datenum_in) || ~isnumeric(datenum_in)
    errordlg('Input "datenum_in" is empty or non-numeric.', mfilename);
    return
end

if ~exist('time_unit_string', 'var') || ...
   isempty(time_unit_string) || ...
   ~ischar(time_unit_string)
    errordlg('Input "time_unit_string" is missing, empty or non-char.', ...
        mfilename);
    return
end

switch lower(time_unit_string)
    case {'second', 'seconds', 'sec', 's'}
        time_unit = units(1, 'second', 'day');
        
    case {'minute', 'minutes', 'min', 'm'}
        time_unit = units(1, 'minute', 'day');

    case {'hour', 'hours', 'hr', 'h'}
        time_unit = units(1, 'hour', 'day');

    case {'day', 'days', 'd'}
        time_unit = 1;

    case {'month', 'months', 'mon'}
        % Break up the input into year, month, day components.
        [yr, mon, day, hr, min, sec] = datevec(datenum_in);
        
        % Are we halfway through the month?
        datenum_start_of_this_month = datenum(yr, mon, ones(size(day)), zeros(size(hr)), zeros(size(min)), zeros(size(sec)));
        datenum_start_of_next_month = datenum(yr, mon + 1, ones(size(day)), zeros(size(hr)), zeros(size(min)), zeros(size(sec)));
        round_up_to_next_month_syndrome = (datenum_start_of_next_month - datenum_in) < (datenum_in - datenum_start_of_this_month);
        boost_vector = zeros(size(datenum_in));
        boost_vector(round_up_to_next_month_syndrome) = 1;
        datenum_rounded = datenum(yr, mon + boost_vector, ones(size(day)), zeros(size(hr)), zeros(size(min)), zeros(size(sec)));
        return

    case {'year', 'years', 'yr'}
        % Break up the input into year, month, day components.
        [yr, mon, day, hr, min, sec] = datevec(datenum_in);
        
        % Are we halfway through the year?
        datenum_start_of_this_year = datenum(yr, ones(size(mon)), ones(size(day)), zeros(size(hr)), zeros(size(min)), zeros(size(sec)));
        datenum_start_of_next_year = datenum(yr + 1, ones(size(mon)), ones(size(day)), zeros(size(hr)), zeros(size(min)), zeros(size(sec)));
        round_up_to_next_year_syndrome = (datenum_start_of_next_year - datenum_in) < (datenum_in - datenum_start_of_this_year);
        boost_vector = zeros(size(datenum_in));
        boost_vector(round_up_to_next_year_syndrome) = 1;
        datenum_rounded = datenum(yr + boost_vector, ones(size(mon)), ones(size(day)), zeros(size(hr)), zeros(size(min)), zeros(size(sec)));
        return
        
    otherwise
        errordlg(['Unknown time unit: "', time_unit_string, '".'], mfilename);
        return
end

if(strcmpi(direction, 'default'))
    datenum_rounded = time_unit * round(datenum_in / time_unit);
elseif(strcmpi(direction, 'down'))
    datenum_rounded = time_unit * floor(datenum_in / time_unit);
elseif(strcmpi(direction, 'up'))
     datenum_rounded = time_unit * ceil(datenum_in / time_unit);
end
    
end

janez

janez (view profile)

Andrea

Andrea (view profile)

Nice one, thanks. You can add the possibility of rounding down, up or scientifically by changing the final "round" with floor, ceil or leave it to round (and possibly make the user decide with an argument to the function)

Updates

1.1

Fixed H1 comment line so "lookfor" will work.

MATLAB Release
MATLAB 7.9 (R2009b)
Acknowledgements

Inspired by: units.m

Inspired: Round Serial Date Numbers or Date Vectors

Download apps, toolboxes, and other File Exchange content using Add-On Explorer in MATLAB.

» Watch video