Commit 9efcb147 authored by Fabian Wachsmann's avatar Fabian Wachsmann
Browse files

Merge branch 'develop' of git.mpimet.mpg.de:libcdi into develop

parents dfaae63c d89c8351
......@@ -3,6 +3,18 @@
* using CGRIBEX library version 1.9.4
* Version 1.9.8 released
2019-09-09 Uwe Schulzweida
* grib: added support for start date for accum, avg, range and diff
2019-09-08 Uwe Schulzweida
* time axis: added support for datatype integer
2019-09-06 Uwe Schulzweida
* gribapiDefTime: adjust reference time if necessary (bug fix) [report: Helmut Haak]
2019-08-28 Uwe Schulzweida
* find_leadtime() bug fix
......
......@@ -52,5 +52,5 @@ Porting:
Contact:
Send questions, comments and bug reports to <http://mpimet.mpg.de/cdi>
Send questions, comments and bug reports to <https://mpimet.mpg.de/cdi>
......@@ -7,7 +7,7 @@
AC_PREREQ([2.69])
LT_PREREQ([2.4.6])
AC_INIT([cdi], [1.9.8rc2], [http://mpimet.mpg.de/cdi])
AC_INIT([cdi], [1.9.8rc3], [https://mpimet.mpg.de/cdi])
AC_DEFINE_UNQUOTED(CDI, ["$PACKAGE_VERSION"], [CDI version])
......
......@@ -8,10 +8,10 @@
\bibitem[ECHAM]{ECHAM} \ \\
\href{http://www.mpimet.mpg.de/wissenschaft/publikationen/reports.html}
\href{https://www.mpimet.mpg.de/fileadmin/publikationen/Reports/max_scirep_349.pdf}
{The atmospheric general circulation model ECHAM5},
from the
\href{http://www.mpimet.mpg.de}
\href{https://www.mpimet.mpg.de}
{Max Planck Institute for Meteorologie}
......@@ -38,14 +38,14 @@
\bibitem[MPIOM]{MPIOM} \ \\
The ocean model MPIOM,
from the
\href{http://www.mpimet.mpg.de}
\href{https://www.mpimet.mpg.de}
{Max Planck Institute for Meteorologie}
\bibitem[REMO]{REMO} \ \\
The regional climate model REMO,
from the
\href{http://www.mpimet.mpg.de}
\href{https://www.mpimet.mpg.de}
{Max Planck Institute for Meteorologie}
\end{thebibliography}
......@@ -2,7 +2,7 @@
The interface is independent from a specific data format and has a C and Fortran API.
{\CDI} was developed for a fast and machine independent access to GRIB
and NetCDF datasets with the same interface.
The local \href{http://www.mpimet.mpg.de/}{MPI-MET} data formats SERVICE, EXTRA and
The local \href{https://www.mpimet.mpg.de/}{MPI-MET} data formats SERVICE, EXTRA and
IEG are also supported.
......
......@@ -3,10 +3,12 @@
int main(void)
{
const int nlon = 12; // Number of longitudes
const int nlat = 6; // Number of latitudes
const int nlev = 5; // Number of levels
const int nts = 3; // Number of time steps
enum {
nlon = 12, // Number of longitudes
nlat = 6, // Number of latitudes
nlev = 5, // Number of levels
nts = 3, // Number of time steps
};
size_t nmiss;
double var1[nlon*nlat];
double var2[nlon*nlat*nlev];
......
......@@ -3,10 +3,12 @@
int main(void)
{
const int nlon = 12; // Number of longitudes
const int nlat = 6; // Number of latitudes
const int nlev = 5; // Number of levels
const int nts = 3; // Number of time steps
enum {
nlon = 12, // Number of longitudes
nlat = 6, // Number of latitudes
nlev = 5, // Number of levels
nts = 3, // Number of time steps
};
size_t nmiss;
double var1[nlon*nlat];
double var2[nlon*nlat*nlev];
......
......@@ -3,10 +3,12 @@
int main(void)
{
const int nlon = 12; // Number of longitudes
const int nlat = 6; // Number of latitudes
const int nlev = 5; // Number of levels
const int nts = 3; // Number of time steps
enum {
nlon = 12, // Number of longitudes
nlat = 6, // Number of latitudes
nlev = 5, // Number of levels
nts = 3, // Number of time steps
};
size_t nmiss = 0;
double lons[] = {0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330};
double lats[] = {-75, -45, -15, 15, 45, 75};
......
1 ,PROGRAM CDIWRITE
PROGRAM CDIWRITE
IMPLICIT NONE
......
......@@ -3,10 +3,12 @@
int main(void)
{
const int nlon = 12; // Number of longitudes
const int nlat = 6; // Number of latitudes
const int nlev = 5; // Number of levels
const int nts = 3; // Number of time steps
enum {
nlon = 12, // Number of longitudes
nlat = 6, // Number of latitudes
nlev = 5, // Number of levels
nts = 3, // Number of time steps
};
int nmiss = 0;
double lons[] = {0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330};
double lats[] = {-75, -45, -15, 15, 45, 75};
......
......@@ -80,7 +80,7 @@ void cdfComment(int ncid)
strcat(comment, "??");
else
strcat(comment, libvers);
strcat(comment, " (http://mpimet.mpg.de/cdi)");
strcat(comment, " (https://mpimet.mpg.de/cdi)");
}
cdf_put_att_text(ncid, NC_GLOBAL, "CDI", strlen(comment), comment);
......
#ifndef CDI_KEY_H
#define CDI_KEY_H
#include "cdi_limits.h"
// CDI key
typedef struct {
......
......@@ -196,6 +196,7 @@ const char *cgribexLibraryVersion(void);
void gribDebug(int debug);
void gribSetCalendar(int calendar);
void gribDateTimeX(int *isec1, int *date, int *time, int *startDate, int *startTime);
void gribDateTime(int *isec1, int *date, int *time);
int gribRefDate(int *isec1);
int gribRefTime(int *isec1);
......
This diff is collapsed.
......@@ -158,13 +158,11 @@ static
int setBaseTime(const char *timeunits, taxis_t *taxis)
{
int taxistype = TAXIS_ABSOLUTE;
int64_t rdate = -1;
int rtime = -1;
size_t len = strlen(timeunits);
while ( isspace(*timeunits) && len ) { timeunits++; len--; }
char *restrict tu = (char *)Malloc((len+1) * sizeof(char));
char *tu = (char *)Malloc((len+1) * sizeof(char));
for ( size_t i = 0; i < len; i++ ) tu[i] = (char)tolower((int)timeunits[i]);
tu[len] = 0;
......@@ -182,8 +180,7 @@ int setBaseTime(const char *timeunits, taxis_t *taxis)
{
while ( isspace(tu[pos]) ) ++pos;
if ( strStartsWith(tu+pos, "since") )
taxistype = TAXIS_RELATIVE;
if ( strStartsWith(tu+pos, "since") ) taxistype = TAXIS_RELATIVE;
while ( pos < len && !isspace(tu[pos]) ) ++pos;
if ( tu[pos] )
......@@ -211,13 +208,13 @@ int setBaseTime(const char *timeunits, taxis_t *taxis)
}
else if ( taxistype == TAXIS_RELATIVE )
{
int64_t rdate = -1;
int rtime = -1;
scanTimeString(tu+pos, &rdate, &rtime);
taxis->rdate = rdate;
taxis->rtime = rtime;
if ( CDI_Debug )
Message("rdate = %lld rtime = %d", rdate, rtime);
if ( CDI_Debug ) Message("rdate = %lld rtime = %d", rdate, rtime);
}
}
}
......@@ -227,8 +224,7 @@ int setBaseTime(const char *timeunits, taxis_t *taxis)
Free(tu);
if ( CDI_Debug )
Message("taxistype = %d unit = %d", taxistype, timeunit);
if ( CDI_Debug ) Message("taxistype = %d unit = %d", taxistype, timeunit);
return 0;
}
......@@ -4103,7 +4099,8 @@ int cdfInqContents(stream_t *streamptr)
if ( ncvars[nctimevarid].units[0] )
ptaxisDefUnits(taxis, ncvars[nctimevarid].units);
int datatype = (ncvars[nctimevarid].xtype == NC_FLOAT) ? CDI_DATATYPE_FLT32 : CDI_DATATYPE_FLT64;
int xtype = ncvars[nctimevarid].xtype;
int datatype = (xtype == NC_INT) ? CDI_DATATYPE_INT32 : ((xtype == NC_FLOAT) ? CDI_DATATYPE_FLT32 : CDI_DATATYPE_FLT64);
ptaxisDefDatatype(taxis, datatype);
}
......
#ifdef HAVE_CONFIG_H
# include "config.h"
#include "config.h"
#endif
#ifdef HAVE_LIBNETCDF
......@@ -12,10 +12,10 @@
#include "stream_cdf.h"
#include "cdf_int.h"
static
int cdfDefTimeBounds(int fileID, int nctimevarid, int nctimedimid, const char *taxis_name, taxis_t* taxis)
{
int time_bndsid = -1;
int dims[2];
dims[0] = nctimedimid;
......@@ -48,6 +48,8 @@ int cdfDefTimeBounds(int fileID, int nctimevarid, int nctimedimid, const char *t
bndsAttValLen = tmpstrLen;
bndsAttVal = tmpstr;
}
int time_bndsid = -1;
cdf_def_var(fileID, bndsAttVal, NC_DOUBLE, 2, dims, &time_bndsid);
cdf_put_att_text(fileID, nctimevarid, bndsAttName, bndsAttValLen, bndsAttVal);
......@@ -137,9 +139,6 @@ void cdfDefCalendar(int fileID, int ncvarid, int calendar)
void cdfDefTime(stream_t* streamptr)
{
int time_varid;
int time_dimid;
int time_bndsid = -1;
static const char default_name[] = "time";
if ( streamptr->basetime.ncvarid != CDI_UNDEFID ) return;
......@@ -152,15 +151,18 @@ void cdfDefTime(stream_t* streamptr)
taxis_t *taxis = &streamptr->tsteps[0].taxis;
const char *taxis_name = (taxis->name && taxis->name[0]) ? taxis->name : default_name ;
int time_dimid;
cdf_def_dim(fileID, taxis_name, NC_UNLIMITED, &time_dimid);
streamptr->basetime.ncdimid = time_dimid;
const nc_type xtype = (taxis->datatype == CDI_DATATYPE_FLT32) ? NC_FLOAT : NC_DOUBLE;
cdf_def_var(fileID, taxis_name, xtype, 1, &time_dimid, &time_varid);
const int datatype = taxis->datatype;
const nc_type xtype = (datatype == CDI_DATATYPE_INT32) ? NC_INT : ((datatype == CDI_DATATYPE_FLT32) ? NC_FLOAT : NC_DOUBLE);
int time_varid;
cdf_def_var(fileID, taxis_name, xtype, 1, &time_dimid, &time_varid);
streamptr->basetime.ncvarid = time_varid;
#if defined (HAVE_NETCDF4)
#ifdef HAVE_NETCDF4
if ( streamptr->filetype == CDI_FILETYPE_NC4 || streamptr->filetype == CDI_FILETYPE_NC4C )
{
const size_t chunk = 512;
......@@ -176,7 +178,7 @@ void cdfDefTime(stream_t* streamptr)
if ( taxis->has_bounds )
{
time_bndsid = cdfDefTimeBounds(fileID, time_varid, time_dimid, taxis_name, taxis);
int time_bndsid = cdfDefTimeBounds(fileID, time_varid, time_dimid, taxis_name, taxis);
streamptr->basetime.ncvarboundsid = time_bndsid;
}
......@@ -184,12 +186,10 @@ void cdfDefTime(stream_t* streamptr)
cdfDefTimeUnits(unitstr, taxis);
size_t len = strlen(unitstr);
if (len) cdf_put_att_text(fileID, time_varid, "units", len, unitstr);
// if ( len && taxis->has_bounds ) cdf_put_att_text(fileID, time_bndsid, "units", len, unitstr);
if ( taxis->calendar != -1 )
{
cdfDefCalendar(fileID, time_varid, taxis->calendar);
// ( taxis->has_bounds ) cdfDefCalendar(fileID, time_bndsid, taxis->calendar);
}
if ( taxis->type == TAXIS_FORECAST )
......@@ -214,7 +214,6 @@ void cdfDefTime(stream_t* streamptr)
if ( streamptr->ncmode == 2 ) cdf_enddef(fileID);
}
#endif
/*
* Local Variables:
......
......@@ -84,6 +84,7 @@ void cgribexDelete(void *cgribex)
int grib1Sections(unsigned char *gribbuffer, long gribbufsize, unsigned char **pdsp,
unsigned char **gdsp, unsigned char **bmsp, unsigned char **bdsp, long *gribrecsize);
static
size_t cgribexSection2Length(void *gribbuffer, size_t gribbuffersize)
{
long sec2len = 0;
......@@ -720,7 +721,9 @@ int cgribexScanTimestep1(stream_t *streamptr)
off_t recpos = 0;
void *gribbuffer = NULL;
size_t buffersize = 0;
int leveltype = 0, level1 = 0, level2 = 0, vdate = 0, vtime = 0;
int leveltype = 0, level1 = 0, level2 = 0;
int vdate = 0, vtime = 0;
int sdate = 0, stime = 0;
DateTime datetime, datetime0 = { LONG_MIN, LONG_MIN };
unsigned recID;
int nrecs_scanned = 0;
......@@ -746,8 +749,8 @@ int cgribexScanTimestep1(stream_t *streamptr)
unsigned nrecs = 0;
while (true)
{
size_t recsize = gribGetSize(fileID);
recpos = fileGetPos(fileID);
const size_t recsize = gribGetSize(fileID);
recpos = fileGetPos(fileID);
if ( recsize == 0 )
{
......@@ -781,7 +784,7 @@ int cgribexScanTimestep1(stream_t *streamptr)
cgribexGetLevel(isec1, &leveltype, &level1, &level2);
gribDateTime(isec1, &vdate, &vtime);
gribDateTimeX(isec1, &vdate, &vtime, &sdate, &stime);
if ( nrecs == 0 )
{
......@@ -854,11 +857,13 @@ int cgribexScanTimestep1(stream_t *streamptr)
taxis->unit = tunit;
taxis->type = fcast ? TAXIS_RELATIVE : TAXIS_ABSOLUTE;
int taxisID = taxisCreate(taxis->type);
const int taxisID = taxisCreate(taxis->type);
taxis->rdate = rdate;
taxis->rtime = rtime;
taxis->vdate = (int64_t)datetime0.date;
taxis->vtime = (int)datetime0.time;
taxis->sdate = sdate;
taxis->stime = stime;
const int vlistID = streamptr->vlistID;
vlistDefTaxis(vlistID, taxisID);
......@@ -879,7 +884,9 @@ int cgribexScanTimestep2(stream_t * streamptr)
{
int lmv = 0, iret = 0;
off_t recpos = 0;
int leveltype = 0, level1 = 0, level2 = 0, vdate = 0, vtime = 0;
int leveltype = 0, level1 = 0, level2 = 0;
int vdate = 0, vtime = 0;
int sdate = 0, stime = 0;
DateTime datetime, datetime0 = { LONG_MIN, LONG_MIN };
int recID = 0;
bool warn_numavg = true;
......@@ -916,7 +923,7 @@ int cgribexScanTimestep2(stream_t * streamptr)
{
if ( rindex > nrecords ) break;
size_t recsize = gribGetSize(fileID);
const size_t recsize = gribGetSize(fileID);
recpos = fileGetPos(fileID);
if ( recsize == 0 )
{
......@@ -939,7 +946,7 @@ int cgribexScanTimestep2(stream_t * streamptr)
cgribexGetLevel(isec1, &leveltype, &level1, &level2);
gribDateTime(isec1, &vdate, &vtime);
gribDateTimeX(isec1, &vdate, &vtime, &sdate, &stime);
if ( rindex == 0 )
{
......@@ -956,6 +963,8 @@ int cgribexScanTimestep2(stream_t * streamptr)
taxis->unit = cgribexGetTimeUnit(isec1);
taxis->vdate = vdate;
taxis->vtime = vtime;
taxis->sdate = sdate;
taxis->stime = stime;
datetime0.date = vdate;
datetime0.time = vtime;
......@@ -965,8 +974,7 @@ int cgribexScanTimestep2(stream_t * streamptr)
if ( ISEC1_AvgNum )
{
if ( taxis->numavg && warn_numavg &&
(taxis->numavg != ISEC1_AvgNum) )
if ( taxis->numavg && warn_numavg && (taxis->numavg != ISEC1_AvgNum) )
{
// Warning("Changing numavg from %d to %d not supported!", taxis->numavg, ISEC1_AvgNum);
warn_numavg = false;
......@@ -1078,7 +1086,9 @@ int cgribexScanTimestep(stream_t * streamptr)
{
int lmv = 0, iret = 0;
off_t recpos = 0;
int leveltype = 0, level1 = 0, level2 = 0, vdate = 0, vtime = 0;
int leveltype = 0, level1 = 0, level2 = 0;
int vdate = 0, vtime = 0;
int sdate = 0, stime = 0;
DateTime datetime, datetime0 = { LONG_MIN, LONG_MIN };
int vrecID, recID = 0;
bool warn_numavg = true;
......@@ -1112,7 +1122,7 @@ int cgribexScanTimestep(stream_t * streamptr)
if ( rindex > nrecs ) break;
const size_t recsize = gribGetSize(fileID);
recpos = fileGetPos(fileID);
recpos = fileGetPos(fileID);
if ( recsize == 0 )
{
streamptr->ntsteps = streamptr->rtsteps + 1;
......@@ -1141,14 +1151,14 @@ int cgribexScanTimestep(stream_t * streamptr)
cgribexGetLevel(isec1, &leveltype, &level1, &level2);
gribDateTime(isec1, &vdate, &vtime);
gribDateTimeX(isec1, &vdate, &vtime, &sdate, &stime);
if ( rindex == nrecs ) break;
if ( rindex == 0 )
{
const int vlistID = streamptr->vlistID;
int taxisID = vlistInqTaxis(vlistID);
const int taxisID = vlistInqTaxis(vlistID);
if ( taxisInqType(taxisID) == TAXIS_RELATIVE )
{
taxis->type = TAXIS_RELATIVE;
......@@ -1162,6 +1172,8 @@ int cgribexScanTimestep(stream_t * streamptr)
taxis->unit = cgribexGetTimeUnit(isec1);
taxis->vdate = vdate;
taxis->vtime = vtime;
taxis->sdate = sdate;
taxis->stime = stime;
datetime0.date = vdate;
datetime0.time = vtime;
......@@ -1169,8 +1181,7 @@ int cgribexScanTimestep(stream_t * streamptr)
if ( ISEC1_AvgNum )
{
if ( taxis->numavg && warn_numavg &&
(taxis->numavg != ISEC1_AvgNum) )
if ( taxis->numavg && warn_numavg && (taxis->numavg != ISEC1_AvgNum) )
{
/*
Warning("Changing numavg from %d to %d not supported!", streamptr->tsteps[tsID].taxis.numavg, ISEC1_AvgNum);
......@@ -1407,8 +1418,8 @@ void cgribexDefParam(int *isec1, int param)
}
static
int cgribexDefTimerange(int tsteptype, int factor, int calendar,
int rdate, int rtime, int vdate, int vtime, int *pip1, int *pip2)
int cgribexDefTimerange(int tsteptype, int factor, int calendar, int rdate, int rtime,
int vdate, int vtime, int sdate, int stime, int *pip1, int *pip2)
{
int year, month, day, hour, minute, second;
int64_t julday1, julday2, days;
......@@ -1431,15 +1442,27 @@ int cgribexDefTimerange(int tsteptype, int factor, int calendar,
const int ip = (int) ((days*86400.0 + secs)/factor);
if ( (ip > 255) && (tsteptype == TSTEP_INSTANT) ) tsteptype = TSTEP_INSTANT3;
int ipx = 0;
if (sdate != 0 && (tsteptype == TSTEP_RANGE || tsteptype == TSTEP_AVG || tsteptype == TSTEP_ACCUM || tsteptype == TSTEP_DIFF))
{
cdiDecodeDate(sdate, &year, &month, &day);
cdiDecodeTime(stime, &hour, &minute, &second);
encode_juldaysec(calendar, year, month, day, hour, minute, second, &julday2, &secofday2);
(void) julday_sub(julday1, secofday1, julday2, secofday2, &days, &secs);
ipx = (int) ((days*86400.0 + secs)/factor);
}
// clang-format off
switch ( tsteptype )
{
case TSTEP_INSTANT: timerange = 0; ip1 = ip; ip2 = 0; break;
case TSTEP_INSTANT2: timerange = 1; ip1 = 0; ip2 = 0; break;
case TSTEP_RANGE: timerange = 2; ip1 = 0; ip2 = ip; break;
case TSTEP_AVG: timerange = 3; ip1 = 0; ip2 = ip; break;
case TSTEP_ACCUM: timerange = 4; ip1 = 0; ip2 = ip; break;
case TSTEP_DIFF: timerange = 5; ip1 = 0; ip2 = ip; break;
case TSTEP_INSTANT: timerange = 0; ip1 = ip; ip2 = 0; break;
case TSTEP_INSTANT2: timerange = 1; ip1 = 0; ip2 = 0; break;
case TSTEP_RANGE: timerange = 2; ip1 = 0; ip2 = ip; break;
case TSTEP_AVG: timerange = 3; ip1 = 0; ip2 = ip; break;
case TSTEP_ACCUM: timerange = 4; ip1 = ipx; ip2 = ip; break;
case TSTEP_DIFF: timerange = 5; ip1 = 0; ip2 = ip; break;
case TSTEP_INSTANT3:
default: timerange = 10; ip1 = ip/256; ip2 = ip%256; break;
}
......@@ -1520,18 +1543,27 @@ void cgribexDefTime(int *isec1, int vdate, int vtime, int tsteptype, int numavg,
if ( timetype == TAXIS_RELATIVE )
{
const int calendar = taxisInqCalendar(taxisID);
const int rdate = taxisInqRdate(taxisID);
const int rtime = taxisInqRtime(taxisID);
int rdate = taxisInqRdate(taxisID);
int rtime = taxisInqRtime(taxisID);
if (vdate < rdate || (vdate == rdate && vtime < rtime))
{
rdate = vdate;
rtime = vtime;
}
int sdate = taxisInqSdate(taxisID);
int stime = taxisInqStime(taxisID);
int factor = cgribexDefDateTime(isec1, timeunit, rdate, rtime);
int ip1 = 0, ip2 = 0;
timerange = cgribexDefTimerange(tsteptype, factor, calendar, rdate, rtime, vdate, vtime, &ip1, &ip2);
timerange = cgribexDefTimerange(tsteptype, factor, calendar, rdate, rtime, vdate, vtime, sdate, stime, &ip1, &ip2);
if ( ip2 > 0xFF && timeunit < TUNIT_YEAR )
{
timeunit++;
factor = cgribexDefDateTime(isec1, timeunit, rdate, rtime);
timerange = cgribexDefTimerange(tsteptype, factor, calendar, rdate, rtime, vdate, vtime, &ip1, &ip2);
timerange = cgribexDefTimerange(tsteptype, factor, calendar, rdate, rtime, vdate, vtime, sdate, stime, &ip1, &ip2);
}
if ( timerange == -1 || timerange == 3 )
......
......@@ -143,9 +143,35 @@ void gribapiSetDataDateTime(grib_handle *gh, int64_t datadate, int datatime)
}
static
int gribapiGetValidityDateTime(grib_handle *gh, int64_t *vdate, int *vtime)
int gribapiGetTimeUnitFactor(int timeUnits)
{
int tstepRange = 0;
static bool lprint = true;
switch ( timeUnits )
{
case TUNIT_SECOND: return 1; break;
case TUNIT_MINUTE: return 60; break;
case TUNIT_HOUR: return 3600; break;
case TUNIT_3HOURS: return 10800; break;
case TUNIT_6HOURS: return 21600; break;
case TUNIT_12HOURS: return 43200; break;
case TUNIT_DAY: return 86400; break;
default:
if ( lprint )
{
Warning("Time unit %d unsupported", timeUnits);
lprint = false;
}
break;
}
return 0;
}
static
void gribapiGetValidityDateTime(grib_handle *gh, int64_t *vdate, int *vtime, int64_t *startDate, int *startTime)
{
*startDate = 0;
*startTime = 0;
long sigofrtime = 3;
if ( gribEditionNumber(gh) > 1 )
......@@ -153,7 +179,7 @@ int gribapiGetValidityDateTime(grib_handle *gh, int64_t *vdate, int *vtime)
else
GRIB_CHECK(grib_get_long(gh, "timeRangeIndicator", &sigofrtime), 0);
if ( sigofrtime == 3 ) //XXX: This looks like a bug to me, because timeRangeIndicator == 3 does not seem to have the same meaning as significanceOfReferenceTime == 3. I would recommend replacing this condition with `if(!gribapiTimeIsFC())`.
if ( sigofrtime == 3 ) //XXX: This looks like a bug to me, because timeRangeIndicator == 3 does not seem to have the same meaning as significanceOfReferenceTime == 3. I would recommend replacing this condition with `if(!gribapiTimeIsFC())`.
{
gribapiGetDataDateTime(gh, vdate, vtime);
}
......@@ -167,9 +193,6 @@ int gribapiGetValidityDateTime(grib_handle *gh, int64_t *vdate, int *vtime)
int startStep = 0, endStep = 0;
gribapiGetSteps(gh, timeUnits, &startStep, &endStep);
const int range = endStep - startStep;