/* Based on the post date and a proximo type, compute the month and * year this is due. The actual day is filled in below. * * A proximo billing term has multiple parameters: * * due day: day of the month the invoice/bill will be due * * cutoff: day of the month used to decide if the due date will be * in the next month or in the month thereafter. This can be * a negative number in which case the cutoff date is relative * to the end of the month and counting backwards. * Eg: cutoff = -3 would mean 25 in February or 28 in June * * How does it work: * Assume cutoff = 19 and due day = 20 * * * Example 1 post date = 14-06-2010 (European date format) * 14 is less than the cutoff of 19, so the due date will be in the next * month. Since the due day is set to 20, the due date will be * 20-07-2010 * * * Example 2 post date = 22-06-2010 (European date format) * 22 is more than the cutoff of 19, so the due date will be in the month * after next month. Since the due day is set to 20, the due date will be * 20-02-2010 * */ static void compute_monthyear (const GncBillTerm *term, Timespec post_date, int *month, int *year) { int iday, imonth, iyear; int cutoff = term->cutoff; g_return_if_fail (term->type == GNC_TERM_TYPE_PROXIMO); gnc_timespec2dmy (post_date, &iday, &imonth, &iyear); if (cutoff <= 0) cutoff += gnc_timespec_last_mday (post_date); if (iday <= cutoff) { /* We apply this to next month */ imonth++; } else { /* We apply to the following month */ imonth += 2; } if (imonth > 12) { iyear++; imonth -= 12; } if (month) *month = imonth; if (year) *year = iyear; }
/* The GDate setter functions all in the end use g_date_set_time_t, * which in turn relies on localtime and is therefore subject to the * 2038 bug. */ GDate timespec_to_gdate (Timespec ts) { GDate result; gint day, month, year; g_date_clear (&result, 1); gnc_timespec2dmy (ts, &day, &month, &year); g_date_set_dmy (&result, day, static_cast<GDateMonth>(month), year); g_assert(g_date_valid (&result)); return result; }
static gboolean check_conversion (const char * str, Timespec expected_ts) { Timespec ts; int day, month, year; GDate d1, d2; ts = gnc_iso8601_to_timespec_gmt (str); // We test the conversion to GDate against the timespec2dmy // conversion, and also the conversion back to timespec and again // to GDate so that it is still the original GDate gnc_timespec2dmy(ts, &day, &month, &year); d1 = timespec_to_gdate(ts); d2 = timespec_to_gdate(gdate_to_timespec(d1)); if ((g_date_compare(&d1, &d2) != 0) || (g_date_get_day(&d1) != day) || (g_date_get_month(&d1) != month) || (g_date_get_year(&d1) != year)) { fprintf (stderr, "\nmis-converted \"%s\" to GDate. " "Got d1(Y-M-D) = %i-%i-%i, d2(Y-M-D) = %i-%i-%i\n", str, year, month, day, g_date_get_year(&d2), g_date_get_month(&d2), g_date_get_day(&d2)); failure ("misconverted timespec"); return FALSE; } if ((expected_ts.tv_sec != ts.tv_sec) || (expected_ts.tv_nsec != ts.tv_nsec)) { fprintf (stderr, "\nmis-converted \"%s\" to %" G_GUINT64_FORMAT ".%09ld seconds\n" "\twas expecting %" G_GUINT64_FORMAT ".%09ld seconds\n", str, ts.tv_sec, ts.tv_nsec, expected_ts.tv_sec, expected_ts.tv_nsec); failure ("misconverted timespec"); return FALSE; } success ("good conversion"); return TRUE; }