star-meteo

Time varying meteorological data
git clone git://git.meso-star.fr/star-meteo.git
Log | Files | Refs | README | LICENSE

commit d9b64d66ad39a77ac1d33102d1d367bade45beff
parent dd1f655189eb8ea5d5d683450f4d0f8d95350cd6
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Thu, 14 Aug 2025 14:18:50 +0200

Refactor time interval verification

Move the interval duration checks to a separate function to improve the
readability of the analysis code.

Comment on the lack of verification of the order of time intervals: this
is actually unnecessary, as verifying the duration of the intervals also
allows the chronological order to be verified.

Diffstat:
Msrc/smeteo_load.c | 92++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
1 file changed, 66 insertions(+), 26 deletions(-)

diff --git a/src/smeteo_load.c b/src/smeteo_load.c @@ -309,12 +309,59 @@ error: } static res_T +check_interval_duration + (const struct smeteo* smeteo, + const struct txtrdr* txtrdr, + const size_t id, /* Index of the interval to check */ + const double expected_duration) /* [day/1850] */ +{ + const struct smeteo_entry* entries = NULL; + const double eps = expected_duration*1e-6; + double duration = 0; + res_T res = RES_OK; + + ASSERT(smeteo && txtrdr && expected_duration > 0); + ASSERT(id < darray_entry_size_get(&smeteo->entries)); + + entries = darray_entry_cdata_get(&smeteo->entries); + + if(id == 0) { + /* The dates of the intervals are relative to midnight on January 1, 1850. + * In addition, their time is defined at the center of the interval. Thus, + * for the first interval, calculate its duration by multiplying its date + * relative to January 1, 1850 by 2 */ + duration = entries[0].day_1850*2; + } else { + duration = entries[id-0].day_1850 - entries[id-1].day_1850; + } + + if(!eq_eps(duration, expected_duration, eps)) { + ERROR(smeteo, + "%s:%lu: invalid time interval. " + "It is calculated from the \"day_1850\" variables between consecutive " + "intervals. The interval duration must be constant, which is not the " + "case here. " + "Expected duration: %g [day/1850]; current duration: %g [day/1850] -- " + "%g != %g +/- %g [day/1850]\n", + txtrdr_get_name(txtrdr), txtrdr_get_line_num(txtrdr), + expected_duration, duration, expected_duration, duration, eps); + res = RES_BAD_ARG; + goto error; + } + +exit: + return res; +error: + goto exit; +} + +static res_T load_stream(struct smeteo* smeteo, FILE* fp, const char* name) { struct txtrdr* txtrdr = NULL; size_t i = 0; size_t nintervals = 0; - double interval_ref = -1; /* Reference duration of an interval */ + double duration_ref = -1; /* Reference duration of an interval */ res_T res = RES_OK; ASSERT(smeteo && name); @@ -348,40 +395,33 @@ load_stream(struct smeteo* smeteo, FILE* fp, const char* name) if((res = parse_line(smeteo, txtrdr)) != RES_OK) goto error; - #define COMPUTE_TIME_INTERVAL(Id) \ - if(i == 0) { /* Calculate the reference of the interval duration. * * The dates of the intervals are relative to midnight on January 1, 1850. * In addition, their time is defined at the center of the interval. Thus, * for the first interval, calculate its duration by multiplying its date - * relative to January 1, 1850 by 2. This will be the reference duration - * for the intervals */ - interval_ref = darray_entry_cdata_get(&smeteo->entries)[i].day_1850 * 2; + * relative to January 1, 1850 by 2. This will be the reference duration*/ + duration_ref = darray_entry_cdata_get(&smeteo->entries)[i].day_1850 * 2; } else { - /* Check that the interval duration is constant */ - const double interval = - darray_entry_cdata_get(&smeteo->entries)[i-0].day_1850 - - darray_entry_cdata_get(&smeteo->entries)[i-1].day_1850; - const double eps = interval_ref*1e-6; - - if(!eq_eps(interval, interval_ref, eps)) { - ERROR(smeteo, - "%s:%lu: invalid time interval. " - "It is calculated from the `day_1850' variables between consecutive " - "intervals. The interval duration must be constant, which is not the " - "case here. Reference interval: %g; current interval: %g -- " - "%g != %g +/- %g.\n", - txtrdr_get_name(txtrdr), txtrdr_get_line_num(txtrdr), - interval_ref, interval, interval_ref, interval, eps); - res = RES_BAD_ARG; - goto error; - } + res = check_interval_duration(smeteo, txtrdr, i, duration_ref); + if(res != RES_OK) goto error; + + /* Note that although this is a constraint of the smeteo file format, it + * is not actually necessary to check that the intervals are sorted in + * ascending order. Checking the duration of the interval will also reveal + * an invalid order, as the duration would be negative when calculated + * from the temporal center of two consecutive intervals. Unless the + * day_1850 variables are invalid in relation to the date of the + * intervals. But in this situation, checking the order would also give a + * false positive. Not to mention that the correspondence between the date + * and the value day_1850 should then be verified. However, this would be + * difficult to achieve, as converting a date to the "day_1850" format + * seems complicated given all the special cases related to time + * conversion (leap years, leap seconds). It would be interesting to study + * how this is done by the user who generates the smeteo files. */ } - - #undef COMPUTE_TIME_INTERVAL } exit: