diff --git a/src/codes_util.cc b/src/codes_util.cc index 1b73432f8..3ff4ac353 100644 --- a/src/codes_util.cc +++ b/src/codes_util.cc @@ -213,6 +213,38 @@ int is_date_valid(long year, long month, long day, long hour, long minute, doubl return 1; } +// Return 1 if input date is valid. Otherwise 0 +// Note: In the 24-hour time notation, the day begins at midnight, 00:00 or 0:00, +// and the last minute of the day begins at 23:59. +// Where convenient, the notation 24:00 may also be used to refer to midnight +// at the end of a given date — that is, 24:00 of one day is the same time +// as 00:00 of the following day +int is_time_valid(long number) +{ + // number should be 4 digits i.e., HHMM + // Check if the number is a four-digit integer + if (number < 0 || number > 9999) { + return 0; + } + + // Extract hours and minutes + long hours = number / 100; // Get the first two digits as hours + long minutes = number % 100; // Get the last two digits as minutes + + // Check if hours are within the valid range (00-23) + if (hours < 0 || hours > 24) { + return 0; + } + + // Check if minutes are within the valid range (00-59) + if (minutes < 0 || minutes > 59) { + return 0; + } + + // All checks pass + return 1; +} + static float float_epsilon(void) { float floatEps = 1.0; diff --git a/src/eccodes_prototypes.h b/src/eccodes_prototypes.h index e26aace4e..db119f1ce 100644 --- a/src/eccodes_prototypes.h +++ b/src/eccodes_prototypes.h @@ -1328,6 +1328,7 @@ char* codes_getenv(const char* name); int codes_check_grib_ieee_packing_value(int value); int codes_flush_sync_close_file(FILE* f); int is_date_valid(long year, long month, long day, long hour, long minute, double second); +int is_time_valid(long number); // number is HHMM int compute_scaled_value_and_scale_factor(double input, int64_t scaled_value_max, int64_t scale_factor_max, int64_t* ret_value, int64_t* ret_factor); /* grib_util.cc*/ diff --git a/src/grib_accessor_class_g2date.cc b/src/grib_accessor_class_g2date.cc index 4ed01d99e..c85e86b9e 100644 --- a/src/grib_accessor_class_g2date.cc +++ b/src/grib_accessor_class_g2date.cc @@ -123,9 +123,9 @@ static void dump(grib_accessor* a, grib_dumper* dumper) static int unpack_long(grib_accessor* a, long* val, size_t* len) { - int ret = 0; - grib_accessor_g2date* self = (grib_accessor_g2date*)a; + const grib_accessor_g2date* self = (grib_accessor_g2date*)a; + int ret = 0; long year = 0; long month = 0; long day = 0; @@ -145,13 +145,12 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) return GRIB_SUCCESS; } -/* TODO: Check for a valid date */ static int pack_long(grib_accessor* a, const long* val, size_t* len) { - int ret; - long v = val[0]; - grib_accessor_g2date* self = (grib_accessor_g2date*)a; + const grib_accessor_g2date* self = (grib_accessor_g2date*)a; + int ret = GRIB_SUCCESS; + long v = val[0]; long year = 0; long month = 0; long day = 0; @@ -165,6 +164,12 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len) v %= 100; day = v; + if (!is_date_valid(year, month, day, 0, 0, 0)) { + // ECC-1777: For now just a warning. Will later change to an error + fprintf(stderr, "ECCODES WARNING : %s:%s: Date is not valid! year=%ld month=%ld day=%ld\n", + a->cclass->name, __func__, year, month, day); + } + if ((ret = grib_set_long_internal(grib_handle_of_accessor(a), self->day, day)) != GRIB_SUCCESS) return ret; if ((ret = grib_set_long_internal(grib_handle_of_accessor(a), self->month, month)) != GRIB_SUCCESS) diff --git a/src/grib_accessor_class_time.cc b/src/grib_accessor_class_time.cc index d38a53b7c..36aa290c9 100644 --- a/src/grib_accessor_class_time.cc +++ b/src/grib_accessor_class_time.cc @@ -126,12 +126,11 @@ static void dump(grib_accessor* a, grib_dumper* dumper) static int unpack_long(grib_accessor* a, long* val, size_t* len) { - int ret = 0; - grib_accessor_time* self = (grib_accessor_time*)a; - long hour = 0; - long minute = 0; - long second = 0; - grib_handle* hand = grib_handle_of_accessor(a); + const grib_accessor_time* self = (grib_accessor_time*)a; + + int ret = 0; + long hour = 0, minute = 0, second = 0; + grib_handle* hand = grib_handle_of_accessor(a); if ((ret = grib_get_long_internal(hand, self->hour, &hour)) != GRIB_SUCCESS) return ret; @@ -160,54 +159,24 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len) return GRIB_SUCCESS; } -// In the 24-hour time notation, the day begins at midnight, 00:00 or 0:00, -// and the last minute of the day begins at 23:59. -// Where convenient, the notation 24:00 may also be used to refer to midnight -// at the end of a given date — that is, 24:00 of one day is the same time -// as 00:00 of the following day -#if 0 -static bool isValidTime(long number) -{ - // Check if the number is a four-digit integer - if (number < 0 || number > 9999) { - return false; - } - - // Extract hours and minutes - long hours = number / 100; // Get the first two digits as hours - long minutes = number % 100; // Get the last two digits as minutes - - // Check if hours are within the valid range (00-23) - if (hours < 0 || hours > 24) { - return false; - } - - // Check if minutes are within the valid range (00-59) - if (minutes < 0 || minutes > 59) { - return false; - } - - // All checks pass - return true; -} -#endif - static int pack_long(grib_accessor* a, const long* val, size_t* len) { - int ret = 0; - long v = val[0]; - grib_accessor_time* self = (grib_accessor_time*)a; - grib_handle* hand = grib_handle_of_accessor(a); - long hour = 0; - long minute = 0; - long second = 0; + const grib_accessor_time* self = (grib_accessor_time*)a; + + int ret = 0; + long v = val[0]; + grib_handle* hand = grib_handle_of_accessor(a); + long hour = 0, minute = 0, second = 0; if (*len != 1) return GRIB_WRONG_ARRAY_SIZE; - // if (!isValidTime(v)) { - // return GRIB_ENCODING_ERROR; - // } + if (!is_time_valid(v)) { + // ECC-1777: For now just a warning. Will later change to an error + fprintf(stderr, "ECCODES WARNING : %s:%s: Time is not valid! hour=%ld min=%ld sec=%ld\n", + a->cclass->name, __func__, hour, minute, second); + // return GRIB_ENCODING_ERROR; + } hour = v / 100; minute = v % 100; diff --git a/tests/grib_set_fail.sh b/tests/grib_set_fail.sh index 1d850141e..d4c2a0b4e 100755 --- a/tests/grib_set_fail.sh +++ b/tests/grib_set_fail.sh @@ -95,6 +95,18 @@ status=$? set -e [ $status -ne 0 ] +# Bad date +# --------- +input=$ECCODES_SAMPLES_PATH/GRIB2.tmpl +${tools_dir}/grib_set -s dataDate=20180229 $input $outfile > $temp 2>&1 +cat $temp +grep -q "Date is not valid" $temp + +${tools_dir}/grib_set -s dataTime=4261 $input $outfile > $temp 2>&1 +cat $temp +grep -q "Time is not valid" $temp + + # ECC-1359: string that can be converted to an integer # --------------------------------------------------- ${tools_dir}/grib_set -s month:s=6 $ECCODES_SAMPLES_PATH/GRIB2.tmpl $outfile