Fixed bug NCF-175: ncdump -t incorrectly interpreting units attribute

(such as "days") without a base time (such as "since 2007-01-01") as a
time unit.
This commit is contained in:
Russ Rew 2012-06-07 18:14:02 +00:00
parent d144438455
commit 024f318431
5 changed files with 68 additions and 1 deletions

View File

@ -327,7 +327,6 @@ cdParseRelunits(cdCalenType timetype, char* relunits, cdUnitTime* unit, cdCompTi
} else {
nconv = sscanf(relunits,"%s since %[^T]T%s",charunits,basetime_1,basetime_2);
}
/* Get the units */
cdTrim(charunits,CD_MAX_RELUNITS);
if(!strncmp(charunits,"sec",3) || !strcmp(charunits,"s")){

View File

@ -108,6 +108,55 @@ is_bounds_var(char *varname, int *pargrpidp, int *parvaridp) {
return false;
}
/* Test if attribute is of form required by cdtime:
* <time_unit> since <base_time>
* where
* <time_unit>:
*/
boolean
is_valid_time_unit(const char *units) {
char charunits[CD_MAX_RELUNITS];
char basetime_1[CD_MAX_CHARTIME];
char basetime_2[CD_MAX_CHARTIME];
int nconv1, nconv2;
boolean okunit = false;
/* Allow ISO-8601 "T" date-time separator as well as blank separator */
nconv1 = sscanf(units,"%s since %[^T]T%s", charunits, basetime_1, basetime_2);
nconv2 = sscanf(units,"%s since %s %s", charunits, basetime_1, basetime_2);
if (!(nconv1 > 1 || nconv2 > 1))
return false;
/* Check for unit compatible with cdtime library, no attempt
* to enforce CF-compliance or udunits compliance here ... */
if(!strncmp(charunits,"sec",3) || !strcmp(charunits,"s")){
okunit = true;
}
else if(!strncmp(charunits,"min",3) || !strcmp(charunits,"mn")){
okunit = true;
}
else if(!strncmp(charunits,"hour",4) || !strcmp(charunits,"hr")){
okunit = true;
}
else if(!strncmp(charunits,"day",3) || !strcmp(charunits,"dy")){
okunit = true;
}
else if(!strncmp(charunits,"week",4) || !strcmp(charunits,"wk")){
okunit = true;
}
else if(!strncmp(charunits,"month",5) || !strcmp(charunits,"mo")){
okunit = true;
}
else if(!strncmp(charunits,"season",6)){
okunit = true;
}
else if(!strncmp(charunits,"year",4) || !strcmp(charunits,"yr")){
okunit = true;
}
if (!okunit)
return false;
return true;
}
/* Return true only if this is a "bounds" attribute */
boolean
is_bounds_att(ncatt_t *attp) {
@ -158,6 +207,10 @@ get_timeinfo(int ncid1, int varid1, ncvar_t *vp) {
units = emalloc(uatt.len + 1);
NC_CHECK(nc_get_att(ncid, varid, "units", units));
units[uatt.len] = '\0';
if(!is_valid_time_unit(units)) {
free(units);
return;
}
/* check for calendar attribute (not required even for time vars) */
vp->timeinfo = (timeinfo_t *)emalloc(sizeof(timeinfo_t));
memset((void*)vp->timeinfo,0,sizeof(timeinfo_t));

View File

@ -8,6 +8,7 @@
extern void insert_bounds_info(int ncid, int varid, ncatt_t att);
extern int is_valid_time_unit(const char *units);
extern int is_bounds_att(ncatt_t *attp);
extern void get_timeinfo(int ncid, int varid, ncvar_t *vp);
extern void print_att_times(int ncid, int varid, ncatt_t att);

View File

@ -82,6 +82,11 @@ variables:
// "1804-04-26", "1804-04-27", "1804-04-28", "1804-04-29",
// "1804-04-30"
double t3_bnds(t3, bnds) ;
int t4 ;
t4:units = "days" ;
t4:att1 = 1 ;
t4:att2 = 5, 6 ;
t4:att3 = 7.125f, 8.75f ;
data:
t1_days = "2009-01-01" ;
@ -132,4 +137,6 @@ data:
"1804-01-10 12", "1804-01-11 12",
"1804-01-11 12", "1804-01-12 12",
"1804-01-12 12", "1804-01-13 12" ;
t4 = _ ;
}

View File

@ -86,6 +86,13 @@ variables:
t3:time5 = 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120 ;
double t3_bnds(t3, bnds) ; // no attributes, since a cell bounds variable
// test -t bug fix, time unit without base time should not interpret numeric atts as times
int t4 ;
t4:units = "days" ;
t4:att1 = 1 ;
t4:att2 = 5, 6 ;
t4:att3 = 7.125f, 8.75f ;
data:
// Should all represent 2009-01-01 00:00:00
t1_days = 185900;