Loss of precision with netcdf time when using datenum
5 views (last 30 days)
Show older comments
Hi there,
I am trying to read the time variable in from an netcdf file and convert it to datenum values but the end time always seems to fall short (26-11-2005 instead of 01-01-2006).
The time variable from the netcdf file is in 'days since 1860-01-01 00:00:00' and in '365_day' format but I am having trouble getting the proper datenum for the data. The time format is also 'double' precision so I am not sure why I am going wrong when I use the following for example:
time1980_05 = timestamp1980_05' + datenum('1860-01-01 00:00:00');
Any ideas?
1 Comment
Campion Loong
on 4 Feb 2016
Hi Mashtine,
It is a little difficult to know what's going on without some sample input and codes from your attempt. In general though, the datetime type (available for R2014b and up) is preferred to datenum - for one it has much better precision. You may want to give it a try.
Accepted Answer
Kelly Kearney
on 4 Feb 2016
Edited: Kelly Kearney
on 4 Feb 2016
I wrote a function, daynoleap2datenum, that does the conversion that Peter suggested (in a slightly simpler manner... I just figure out which years need a leap day and bump the numbers up one at those locations). It converts the output to either datenumbers or datetime objects, so it can work regardless of Matlab version.
As you can see in this example, the missing leap days are what lead to your simple addition method coming up a bit short:
t = [0 58:60 364]';
t1 = datetime(2000,1,1) + t
t2 = daynoleap2datenum(t, 2000, 'dt')
t1 =
01-Jan-2000 00:00:00
28-Feb-2000 00:00:00
29-Feb-2000 00:00:00
01-Mar-2000 00:00:00
30-Dec-2000 00:00:00
t2 =
01-Jan-2000 00:00:00
28-Feb-2000 00:00:00
01-Mar-2000 00:00:00
02-Mar-2000 00:00:00
31-Dec-2000 00:00:00
0 Comments
More Answers (1)
Peter Perkins
on 4 Feb 2016
Mashtine, I'm not super familiar with netCDF, but "365 day format" and this
>> dt = between(datetime(2005,11,26),datetime(2006,1,1),'days')
dt =
36d
>> (2006-1860)/4
ans =
36.5
suggests that this is a leap day issue. I imagine you could solve this using datetime, if you have R2014b or later. This might be something like what you are looking for:
>> y = [datetime(1860,1,0) datetime(1860,2,28) + calyears(0:5)]
y =
Columns 1 through 6
31-Dec-1859 28-Feb-1860 28-Feb-1861 28-Feb-1862 28-Feb-1863 28-Feb-1864
Column 7
28-Feb-1865
>> % how many days from Feb 28 in year(i) to Feb 28 in year(i+1)
>> d = caldiff(y,'days')
d =
59d 366d 365d 365d 365d 366d
>> d = caldays(d)
d =
59 366 365 365 365 366
>> % which years have leap days?
>> hasLeapDay = (d == 366)
hasLeapDay =
0 1 0 0 0 1
>> adjust = cumsum(hasLeapDay)
adjust =
0 1 1 1 1 2
>> breakPoints = [1 cumsum(d)+1]
breakPoints =
1 60 426 791 1156 1521 1887
% try it out on some "365 day" dates
>> netcdfDay = [(58:61) (58:61)+365 (58:61)+2*365 (58:61)+3*365]
netcdfDay =
Columns 1 through 7
58 59 60 61 423 424 425
Columns 8 through 14
426 788 789 790 791 1153 1154
Columns 15 through 16
1155 1156
>> realDay = netcdfDay + discretize(netcdfDay,breakPoints,adjust)
>> realDay =
Columns 1 through 7
58 59 61 62 424 425 426
Columns 8 through 14
427 789 790 791 792 1154 1155
Columns 15 through 16
1156 1157
>> datestr(realDay + datenum([1860,1,0]))
ans =
27-Feb-1860
28-Feb-1860
01-Mar-1860
02-Mar-1860
27-Feb-1861
28-Feb-1861
01-Mar-1861
02-Mar-1861
27-Feb-1862
28-Feb-1862
01-Mar-1862
02-Mar-1862
27-Feb-1863
28-Feb-1863
01-Mar-1863
02-Mar-1863
5 Comments
Kelly Kearney
on 16 Feb 2016
The datetime object and associated functions were introduced in R2014b, so if you're running an older version, you won't be able to use Peter's code. But I really suggest giving my daynoleap2datenum function a try... it's pretty simple, version independent, and accounts for the 365-day calendar:
S = load('sampledata.mat');
dn = daynoleap2datenum(S.timestamp1980_05, 1860);
datestr(dn([1 end]))
ans =
01-Jan-1980 03:00:00
01-Jan-2006 00:00:00
See Also
Categories
Find more on NetCDF 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!