[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Octave-bug-tracker] [bug #59979] Unexpected format for output from date
From: |
John W. Eaton |
Subject: |
[Octave-bug-tracker] [bug #59979] Unexpected format for output from datevec |
Date: |
Mon, 1 Feb 2021 11:37:45 -0500 (EST) |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0 |
Follow-up Comment #16, bug #59979 (project octave):
Neglecting for a moment any strange display issues that might be due to
rounding (like showing 19 minutes and 60 seconds instead of 20 minutes and 0
seconds) I find the following results quite surprising:
octave> datevec (0)
ans =
-1 12 31 0 0 0
Shouldn't that be 0 years, 0 months, 0 days, 0 hours, 0 minutes, and 0
seconds? For comparision, it looks like datevec (1) is correct:
octave> datevec (1)
ans =
0 1 1 0 0 0
Zero years, the first month and day, zero hours, minutes, and seconds.
Similarly, I see what appears to be the correct result for datevec (1.1):
octave> datevec (1.1)
ans =
0 1 1 2 24 0
0.1 days is 144 minutes, or 2 hours and 24 minutes.
So maybe we just need to do the right thing when the datenum is between 0 and
1?
Looking at datevec.m, I see:
## Algorithm: Peter Baum (http://vsg.cape.com/~pbaum/date/date0.htm)
That link is no longer valid. Maybe we could update it? And also
else # datenum input
if (! iscolumn (date))
date_sz = size (date);
do_resize = true;
endif
date = date(:);
## Move day 0 from midnight -0001-12-31 to midnight 0000-3-1
z = double (floor (date) - 60);
## Calculate number of centuries; K1 = 0.25 is to avoid rounding
problems.
a = floor ((z - 0.25) / 36524.25);
## Days within century; K2 = 0.25 is to avoid rounding problems.
b = z - 0.25 + a - floor (a / 4);
## Calculate the year (year starts on March 1).
y = floor (b / 365.25);
## Calculate day in year.
c = fix (b - floor else # datenum input
if (! iscolumn (date))
date_sz = size (date);
do_resize = true;
endif
date = date(:);
## Move day 0 from midnight -0001-12-31 to midnight 0000-3-1
z = double (floor (date) - 60);
## Calculate number of centuries; K1 = 0.25 is to avoid rounding
problems.
a = floor ((z - 0.25) / 36524.25);
## Days within century; K2 = 0.25 is to avoid rounding problems.
b = z - 0.25 + a - floor (a / 4);
## Calculate the year (year starts on March 1).
y = floor (b / 365.25);
## Calculate day in year.
c = fix (b - floor (365.25 * y)) + 1;
## Calculate month in year.
m = fix ((5 * c + 456) / 153);
d = c - fix ((153 * m - 457) / 5);
## Move to Jan 1 as start of year.
++y(m > 12);
m(m > 12) -= 12;
## Convert hour-minute-seconds. Attempt to account for precision of
## datenum format.
fracd = date - floor (date);
tmps = abs (eps*86400*date);
tmps(tmps == 0) = 1;
srnd = 2 .^ floor (- log2 (tmps));
s = round (86400 * fracd .* srnd) ./ srnd;
h = floor (s / 3600);
s -= 3600 * h;
mi = floor (s / 60);
s -= 60 * mi;
endif
(365.25 * y)) + 1;
## Calculate month in year.
m = fix ((5 * c + 456) / 153);
d = c - fix ((153 * m - 457) / 5);
## Move to Jan 1 as start of year.
++y(m > 12);
m(m > 12) -= 12;
## Convert hour-minute-seconds. Attempt to account for precision of
## datenum format.
fracd = date - floor (date);
tmps = abs (eps*86400*date);
tmps(tmps == 0) = 1;
srnd = 2 .^ floor (- log2 (tmps));
s = round (86400 * fracd .* srnd) ./ srnd;
h = floor (s / 3600);
s -= 3600 * h;
mi = floor (s / 60);
s -= 60 * mi;
endif
There seems to be some ad hoc fudging here. What is the real justification
for "K1 = 0.25 is to avoid rounding problems" and "K2 = 0.25 is to avoid
rounding problems"? Are these arbitrary values really helpful in all cases?
Maybe there is a better way? This code appears to be mostly unchanged since
it was added to Octave. (Note also that it was added long ago, before we used
Mercurial, when I was the only one committing changes, so looking at the
Mercurial logs won't give you proper author info.)
In any case, I don't think the algorithm is correct for small datenum values
and that the problems are not just display issues.
_______________________________________________________
Reply to this item at:
<https://savannah.gnu.org/bugs/?59979>
_______________________________________________
Message sent via Savannah
https://savannah.gnu.org/
- [Octave-bug-tracker] [bug #59979] Unexpected format for output from datevec, Philip Nienhuis, 2021/02/01
- [Octave-bug-tracker] [bug #59979] Unexpected format for output from datevec,
John W. Eaton <=
- [Octave-bug-tracker] [bug #59979] Unexpected format for output from datevec, Markus Mützel, 2021/02/01
- [Octave-bug-tracker] [bug #59979] Unexpected format for output from datevec, Markus Mützel, 2021/02/01
- [Octave-bug-tracker] [bug #59979] Unexpected format for output from datevec, John W. Eaton, 2021/02/01
- [Octave-bug-tracker] [bug #59979] Unexpected format for output from datevec, Tasos Papastylianou, 2021/02/01
- [Octave-bug-tracker] [bug #59979] Unexpected format for output from datevec, Markus Mützel, 2021/02/01
- [Octave-bug-tracker] [bug #59979] Unexpected format for output from datevec, Rik, 2021/02/24
- [Octave-bug-tracker] [bug #59979] Unexpected format for output from datevec, Rik, 2021/02/24