25 #include "gnc-datetime.hpp" 33 #define N_(string) string //So that xgettext will find it 44 enum RelativeDateOffset
58 RelativeDateType m_type;
59 RelativeDateOffset m_offset;
60 const char* m_storage;
61 const char* m_display;
62 const char* m_description;
73 static const std::array<GncRelativeDate, 31> reldates
76 RelativeDatePeriod::TODAY,
77 RelativeDateType::LAST,
78 RelativeDateOffset::NONE,
81 N_(
"The current date.")
84 RelativeDatePeriod::ONE_WEEK_AGO,
85 RelativeDateType::LAST,
86 RelativeDateOffset::WEEK,
92 RelativeDatePeriod::ONE_WEEK_AHEAD,
93 RelativeDateType::NEXT,
94 RelativeDateOffset::WEEK,
100 RelativeDatePeriod::ONE_MONTH_AGO,
101 RelativeDateType::LAST,
102 RelativeDateOffset::MONTH,
108 RelativeDatePeriod::ONE_MONTH_AHEAD,
109 RelativeDateType::NEXT,
110 RelativeDateOffset::MONTH,
112 N_(
"One Month Ahead"),
113 N_(
"One Month Ahead.")
116 RelativeDatePeriod::THREE_MONTHS_AGO,
117 RelativeDateType::LAST,
118 RelativeDateOffset::THREE,
120 N_(
"Three Months Ago"),
121 N_(
"Three Months Ago.")
124 RelativeDatePeriod::THREE_MONTHS_AHEAD,
125 RelativeDateType::NEXT,
126 RelativeDateOffset::THREE,
127 "three-months-ahead",
128 N_(
"Three Months Ahead"),
129 N_(
"Three Months Ahead.")
132 RelativeDatePeriod::SIX_MONTHS_AGO,
133 RelativeDateType::LAST,
134 RelativeDateOffset::SIX,
136 N_(
"Six Months Ago"),
137 N_(
"Six Months Ago.")
140 RelativeDatePeriod::SIX_MONTHS_AHEAD,
141 RelativeDateType::NEXT,
142 RelativeDateOffset::SIX,
144 N_(
"Six Months Ahead"),
145 N_(
"Six Months Ahead.")
148 RelativeDatePeriod::ONE_YEAR_AGO,
149 RelativeDateType::LAST,
150 RelativeDateOffset::YEAR,
156 RelativeDatePeriod::ONE_YEAR_AHEAD,
157 RelativeDateType::NEXT,
158 RelativeDateOffset::YEAR,
160 N_(
"One Year Ahead"),
161 N_(
"One Year Ahead.")
164 RelativeDatePeriod::START_THIS_MONTH,
165 RelativeDateType::START,
166 RelativeDateOffset::MONTH,
168 N_(
"Start of this month"),
169 N_(
"First day of the current month.")
172 RelativeDatePeriod::END_THIS_MONTH,
173 RelativeDateType::END,
174 RelativeDateOffset::MONTH,
176 N_(
"End of this month"),
177 N_(
"Last day of the current month.")
180 RelativeDatePeriod::START_PREV_MONTH,
181 RelativeDateType::START,
182 RelativeDateOffset::MONTH,
184 N_(
"Start of previous month"),
185 N_(
"First day of the previous month.")
188 RelativeDatePeriod::END_PREV_MONTH,
189 RelativeDateType::END,
190 RelativeDateOffset::MONTH,
192 N_(
"End of previous month"),
193 N_(
"Last day of previous month.")
196 RelativeDatePeriod::START_NEXT_MONTH,
197 RelativeDateType::START,
198 RelativeDateOffset::MONTH,
200 N_(
"Start of next month"),
201 N_(
"First day of the next month.")
204 RelativeDatePeriod::END_NEXT_MONTH,
205 RelativeDateType::END,
206 RelativeDateOffset::MONTH,
208 N_(
"End of next month"),
209 N_(
"Last day of next month.")
212 RelativeDatePeriod::START_CURRENT_QUARTER,
213 RelativeDateType::START,
214 RelativeDateOffset::QUARTER,
215 "start-current-quarter",
216 N_(
"Start of current quarter"),
217 N_(
"First day of the current quarterly accounting period.")
220 RelativeDatePeriod::END_CURRENT_QUARTER,
221 RelativeDateType::END,
222 RelativeDateOffset::QUARTER,
223 "end-current-quarter",
224 N_(
"End of current quarter"),
225 N_(
"Last day of the current quarterly accounting period.")
228 RelativeDatePeriod::START_PREV_QUARTER,
229 RelativeDateType::START,
230 RelativeDateOffset::QUARTER,
231 "start-prev-quarter",
232 N_(
"Start of previous quarter"),
233 N_(
"First day of the previous quarterly accounting period.")
236 RelativeDatePeriod::END_PREV_QUARTER,
237 RelativeDateType::END,
238 RelativeDateOffset::QUARTER,
240 N_(
"End of previous quarter"),
241 N_(
"Last day of previous quarterly accounting period.")
244 RelativeDatePeriod::START_NEXT_QUARTER,
245 RelativeDateType::START,
246 RelativeDateOffset::QUARTER,
247 "start-next-quarter",
248 N_(
"Start of next quarter"),
249 N_(
"First day of the next quarterly accounting period.")
252 RelativeDatePeriod::END_NEXT_QUARTER,
253 RelativeDateType::END,
254 RelativeDateOffset::QUARTER,
256 N_(
"End of next quarter"),
257 N_(
"Last day of next quarterly accounting period.")
260 RelativeDatePeriod::START_CAL_YEAR,
261 RelativeDateType::START,
262 RelativeDateOffset::YEAR,
264 N_(
"Start of this year"),
265 N_(
"First day of the current calendar year.")
268 RelativeDatePeriod::END_CAL_YEAR,
269 RelativeDateType::END,
270 RelativeDateOffset::YEAR,
272 N_(
"End of this year"),
273 N_(
"Last day of the current calendar year.")
276 RelativeDatePeriod::START_PREV_YEAR,
277 RelativeDateType::START,
278 RelativeDateOffset::YEAR,
280 N_(
"Start of previous year"),
281 N_(
"First day of the previous calendar year.")
284 RelativeDatePeriod::END_PREV_YEAR,
285 RelativeDateType::END,
286 RelativeDateOffset::YEAR,
288 N_(
"End of previous year"),
289 N_(
"Last day of the previous calendar year.")
292 RelativeDatePeriod::START_NEXT_YEAR,
293 RelativeDateType::START,
294 RelativeDateOffset::YEAR,
296 N_(
"Start of next year"),
297 N_(
"First day of the next calendar year.")
300 RelativeDatePeriod::END_NEXT_YEAR,
301 RelativeDateType::END,
302 RelativeDateOffset::YEAR,
304 N_(
"End of next year"),
305 N_(
"Last day of the next calendar year.")
308 RelativeDatePeriod::START_ACCOUNTING_PERIOD,
309 RelativeDateType::START,
310 RelativeDateOffset::YEAR,
311 "start-prev-fin-year",
312 N_(
"Start of accounting period"),
313 N_(
"First day of the accounting period, as set in the global preferences.")
316 RelativeDatePeriod::END_ACCOUNTING_PERIOD,
317 RelativeDateType::END,
318 RelativeDateOffset::YEAR,
320 N_(
"End of accounting period"),
321 N_(
"Last day of the accounting period, as set in the global preferences.")
328 assert (reldates[static_cast<int>(per)].m_period == per);
329 return reldates[
static_cast<int>(per)];
335 if (per == RelativeDatePeriod::ABSOLUTE)
337 auto reldate = checked_reldate(per);
338 return reldate.m_type == RelativeDateType::LAST ||
339 reldate.m_type == RelativeDateType::NEXT;
345 if (per == RelativeDatePeriod::ABSOLUTE)
347 return checked_reldate(per).m_type == RelativeDateType::START;
353 if (per == RelativeDatePeriod::ABSOLUTE)
355 return checked_reldate(per).m_type == RelativeDateType::END;
361 if (per == RelativeDatePeriod::ABSOLUTE)
363 return checked_reldate(per).m_storage;
369 if (per == RelativeDatePeriod::ABSOLUTE)
371 return checked_reldate(per).m_display;
376 if (per == RelativeDatePeriod::ABSOLUTE)
378 return checked_reldate(per).m_description;
384 auto per = std::find_if(reldates.begin(), reldates.end(),
385 [str](
auto rel) ->
bool 387 return strcmp(str, rel.m_storage) == 0;
389 return per != reldates.end() ? per->m_period : RelativeDatePeriod::ABSOLUTE;
395 auto rdate{checked_reldate(per)};
396 return per == RelativeDatePeriod::START_PREV_YEAR ||
397 per == RelativeDatePeriod::END_PREV_YEAR ||
398 per == RelativeDatePeriod::START_PREV_QUARTER ||
399 per == RelativeDatePeriod::END_PREV_QUARTER ||
400 per == RelativeDatePeriod::START_PREV_MONTH ||
401 per == RelativeDatePeriod::END_PREV_MONTH ||
402 rdate.m_type == LAST;
408 auto rdate{checked_reldate(per)};
409 return per == RelativeDatePeriod::START_NEXT_YEAR ||
410 per == RelativeDatePeriod::END_NEXT_YEAR ||
411 per == RelativeDatePeriod::START_NEXT_QUARTER ||
412 per == RelativeDatePeriod::END_NEXT_QUARTER ||
413 per == RelativeDatePeriod::START_NEXT_MONTH ||
414 per == RelativeDatePeriod::END_NEXT_MONTH ||
415 rdate.m_type == NEXT;
418 static RelativeDateOffset
421 return checked_reldate(per).m_offset;
425 days_in_month(
int month,
int year)
435 normalize_reldate_tm(
struct tm& now)
437 auto delta = (now.tm_mon / 12) + (now.tm_mon < 0 ? -1 : 0);
438 now.tm_mon -= 12 * delta;
439 now.tm_year += delta;
445 if (now.tm_mon-- == 0)
450 now.tm_mday += days_in_month(now.tm_mon, now.tm_year);
451 }
while (now.tm_mday < 1) ;
455 while (now.tm_mday > (delta = days_in_month(now.tm_mon, now.tm_year)))
457 if (now.tm_mon++ == 11)
462 now.tm_mday -= delta;
467 reldate_set_day_and_time(
struct tm& now, RelativeDateType type)
469 if (type == RelativeDateType::START)
471 gnc_tm_set_day_start(&now);
474 else if (type == RelativeDateType::END)
477 auto year_delta = (now.tm_mon / 12) + (now.tm_mon < 0 ? -1 : 0);
478 auto month = now.tm_mon - (12 * year_delta);
479 auto year = now.tm_year + year_delta;
480 now.tm_mday = days_in_month(month, year);
481 gnc_tm_set_day_end(&now);
489 if (period == RelativeDatePeriod::TODAY)
491 if (period == RelativeDatePeriod::START_ACCOUNTING_PERIOD)
492 return gnc_accounting_period_fiscal_start();
493 if (period == RelativeDatePeriod::END_ACCOUNTING_PERIOD)
494 return gnc_accounting_period_fiscal_end();
497 if (period == RelativeDatePeriod::TODAY)
498 return static_cast<time64>(now_t);
499 auto now{
static_cast<tm
>(now_t)};
500 struct tm acct_per{};
502 GNC_PREF_START_CHOICE_ABS))
503 acct_per = static_cast<tm>(
GncDateTime(gnc_accounting_period_fiscal_start()));
505 switch(reldate_offset(period))
507 case RelativeDateOffset::NONE:
510 case RelativeDateOffset::YEAR:
511 if (reldate_is_prev(period))
513 else if (reldate_is_next(period))
520 case RelativeDateOffset::SIX:
521 if (reldate_is_prev(period))
523 else if (reldate_is_next(period))
526 case RelativeDateOffset::QUARTER:
528 auto delta = (now.tm_mon >= acct_per.tm_mon ?
529 ( now.tm_mon - acct_per.tm_mon) % 3 :
530 3 - ((acct_per.tm_mon - now.tm_mon) % 3));
531 now.tm_mon = now.tm_mon - delta;
534 case RelativeDateOffset::THREE:
535 if (reldate_is_prev(period))
537 else if (reldate_is_next(period))
542 case RelativeDateOffset::MONTH:
543 if (reldate_is_prev(period))
545 else if (reldate_is_next(period))
548 case RelativeDateOffset::WEEK:
549 if (reldate_is_prev(period))
551 else if (reldate_is_next(period))
554 reldate_set_day_and_time(now, checked_reldate(period).m_type);
555 normalize_reldate_tm(now);
std::ostream & operator<<(std::ostream &ostr, RelativeDatePeriod per)
Add the display string to the provided std::ostream.
RelativeDatePeriod gnc_relative_date_from_storage_string(const char *str)
Convert a relative date storage string back to a RelativeDatePeriod value.
const char * gnc_relative_date_display_string(RelativeDatePeriod per)
Provide the string representation of a relative date for displaying value to a user.
const char * gnc_relative_date_description(RelativeDatePeriod per)
Provide the description of a relative date.
int gnc_date_get_last_mday(int month, int year)
Get the numerical last date of the month.
time64 gnc_relative_date_to_time64(RelativeDatePeriod period)
Convert a RelativeDatePeriod value to a concrete time64 by applying the value to the current time...
bool gnc_relative_date_is_ending(RelativeDatePeriod per)
Report whether the relative date represents the end of a date range.
bool gnc_relative_date_is_single(RelativeDatePeriod per)
Report whether the relative date represents a period offset to today's date rather than the beginning...
RelativeDatePeriod
Reporting periods relative to the current date.
General utilities for dealing with accounting periods.
bool gnc_relative_date_is_starting(RelativeDatePeriod per)
Report whether the relative date represents the beginning of a date range.
Generic api to store and retrieve preferences.
gboolean gnc_prefs_get_bool(const gchar *group, const gchar *pref_name)
Get a boolean value from the preferences backend.
const char * gnc_relative_date_storage_string(RelativeDatePeriod per)
Provide the string representation of a relative date for persisting the value.
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
Relative date enumeration and manipulation functions.