25 #include "gnc-datetime.hpp" 32 #define N_(string) string //So that xgettext will find it 43 enum RelativeDateOffset
57 RelativeDateType m_type;
58 RelativeDateOffset m_offset;
59 const char* m_storage;
60 const char* m_display;
61 const char* m_description;
72 static const std::array<GncRelativeDate, 31> reldates
75 RelativeDatePeriod::TODAY,
76 RelativeDateType::LAST,
77 RelativeDateOffset::NONE,
80 N_(
"The current date.")
83 RelativeDatePeriod::ONE_WEEK_AGO,
84 RelativeDateType::LAST,
85 RelativeDateOffset::WEEK,
91 RelativeDatePeriod::ONE_WEEK_AHEAD,
92 RelativeDateType::NEXT,
93 RelativeDateOffset::WEEK,
99 RelativeDatePeriod::ONE_MONTH_AGO,
100 RelativeDateType::LAST,
101 RelativeDateOffset::MONTH,
107 RelativeDatePeriod::ONE_MONTH_AHEAD,
108 RelativeDateType::NEXT,
109 RelativeDateOffset::MONTH,
111 N_(
"One Month Ahead"),
112 N_(
"One Month Ahead.")
115 RelativeDatePeriod::THREE_MONTHS_AGO,
116 RelativeDateType::LAST,
117 RelativeDateOffset::THREE,
119 N_(
"Three Months Ago"),
120 N_(
"Three Months Ago.")
123 RelativeDatePeriod::THREE_MONTHS_AHEAD,
124 RelativeDateType::NEXT,
125 RelativeDateOffset::THREE,
126 "three-months-ahead",
127 N_(
"Three Months Ahead"),
128 N_(
"Three Months Ahead.")
131 RelativeDatePeriod::SIX_MONTHS_AGO,
132 RelativeDateType::LAST,
133 RelativeDateOffset::SIX,
135 N_(
"Six Months Ago"),
136 N_(
"Six Months Ago.")
139 RelativeDatePeriod::SIX_MONTHS_AHEAD,
140 RelativeDateType::NEXT,
141 RelativeDateOffset::SIX,
143 N_(
"Six Months Ahead"),
144 N_(
"Six Months Ahead.")
147 RelativeDatePeriod::ONE_YEAR_AGO,
148 RelativeDateType::LAST,
149 RelativeDateOffset::YEAR,
155 RelativeDatePeriod::ONE_YEAR_AHEAD,
156 RelativeDateType::NEXT,
157 RelativeDateOffset::YEAR,
159 N_(
"One Year Ahead"),
160 N_(
"One Year Ahead.")
163 RelativeDatePeriod::START_THIS_MONTH,
164 RelativeDateType::START,
165 RelativeDateOffset::MONTH,
167 N_(
"Start of this month"),
168 N_(
"First day of the current month.")
171 RelativeDatePeriod::END_THIS_MONTH,
172 RelativeDateType::END,
173 RelativeDateOffset::MONTH,
175 N_(
"End of this month"),
176 N_(
"Last day of the current month.")
179 RelativeDatePeriod::START_PREV_MONTH,
180 RelativeDateType::START,
181 RelativeDateOffset::MONTH,
183 N_(
"Start of previous month"),
184 N_(
"First day of the previous month.")
187 RelativeDatePeriod::END_PREV_MONTH,
188 RelativeDateType::END,
189 RelativeDateOffset::MONTH,
191 N_(
"End of previous month"),
192 N_(
"Last day of previous month.")
195 RelativeDatePeriod::START_NEXT_MONTH,
196 RelativeDateType::START,
197 RelativeDateOffset::MONTH,
199 N_(
"Start of next month"),
200 N_(
"First day of the next month.")
203 RelativeDatePeriod::END_NEXT_MONTH,
204 RelativeDateType::END,
205 RelativeDateOffset::MONTH,
207 N_(
"End of next month"),
208 N_(
"Last day of next month.")
211 RelativeDatePeriod::START_CURRENT_QUARTER,
212 RelativeDateType::START,
213 RelativeDateOffset::QUARTER,
214 "start-current-quarter",
215 N_(
"Start of current quarter"),
216 N_(
"First day of the current quarterly accounting period.")
219 RelativeDatePeriod::END_CURRENT_QUARTER,
220 RelativeDateType::END,
221 RelativeDateOffset::QUARTER,
222 "end-current-quarter",
223 N_(
"End of current quarter"),
224 N_(
"Last day of the current quarterly accounting period.")
227 RelativeDatePeriod::START_PREV_QUARTER,
228 RelativeDateType::START,
229 RelativeDateOffset::QUARTER,
230 "start-prev-quarter",
231 N_(
"Start of previous quarter"),
232 N_(
"First day of the previous quarterly accounting period.")
235 RelativeDatePeriod::END_PREV_QUARTER,
236 RelativeDateType::END,
237 RelativeDateOffset::QUARTER,
239 N_(
"End of previous quarter"),
240 N_(
"Last day of previous quarterly accounting period.")
243 RelativeDatePeriod::START_NEXT_QUARTER,
244 RelativeDateType::START,
245 RelativeDateOffset::QUARTER,
246 "start-next-quarter",
247 N_(
"Start of next quarter"),
248 N_(
"First day of the next quarterly accounting period.")
251 RelativeDatePeriod::END_NEXT_QUARTER,
252 RelativeDateType::END,
253 RelativeDateOffset::QUARTER,
255 N_(
"End of next quarter"),
256 N_(
"Last day of next quarterly accounting period.")
259 RelativeDatePeriod::START_CAL_YEAR,
260 RelativeDateType::START,
261 RelativeDateOffset::YEAR,
263 N_(
"Start of this year"),
264 N_(
"First day of the current calendar year.")
267 RelativeDatePeriod::END_CAL_YEAR,
268 RelativeDateType::END,
269 RelativeDateOffset::YEAR,
271 N_(
"End of this year"),
272 N_(
"Last day of the current calendar year.")
275 RelativeDatePeriod::START_PREV_YEAR,
276 RelativeDateType::START,
277 RelativeDateOffset::YEAR,
279 N_(
"Start of previous year"),
280 N_(
"First day of the previous calendar year.")
283 RelativeDatePeriod::END_PREV_YEAR,
284 RelativeDateType::END,
285 RelativeDateOffset::YEAR,
287 N_(
"End of previous year"),
288 N_(
"Last day of the previous calendar year.")
291 RelativeDatePeriod::START_NEXT_YEAR,
292 RelativeDateType::START,
293 RelativeDateOffset::YEAR,
295 N_(
"Start of next year"),
296 N_(
"First day of the next calendar year.")
299 RelativeDatePeriod::END_NEXT_YEAR,
300 RelativeDateType::END,
301 RelativeDateOffset::YEAR,
303 N_(
"End of next year"),
304 N_(
"Last day of the next calendar year.")
307 RelativeDatePeriod::START_ACCOUNTING_PERIOD,
308 RelativeDateType::START,
309 RelativeDateOffset::YEAR,
310 "start-prev-fin-year",
311 N_(
"Start of accounting period"),
312 N_(
"First day of the accounting period, as set in the global preferences.")
315 RelativeDatePeriod::END_ACCOUNTING_PERIOD,
316 RelativeDateType::END,
317 RelativeDateOffset::YEAR,
319 N_(
"End of accounting period"),
320 N_(
"Last day of the accounting period, as set in the global preferences.")
327 assert (reldates[static_cast<int>(per)].m_period == per);
328 return reldates[
static_cast<int>(per)];
334 if (per == RelativeDatePeriod::ABSOLUTE)
336 auto reldate = checked_reldate(per);
337 return reldate.m_type == RelativeDateType::LAST ||
338 reldate.m_type == RelativeDateType::NEXT;
344 if (per == RelativeDatePeriod::ABSOLUTE)
346 return checked_reldate(per).m_type == RelativeDateType::START;
352 if (per == RelativeDatePeriod::ABSOLUTE)
354 return checked_reldate(per).m_type == RelativeDateType::END;
360 if (per == RelativeDatePeriod::ABSOLUTE)
362 return checked_reldate(per).m_storage;
368 if (per == RelativeDatePeriod::ABSOLUTE)
370 return checked_reldate(per).m_display;
375 if (per == RelativeDatePeriod::ABSOLUTE)
377 return checked_reldate(per).m_description;
383 auto per = std::find_if(reldates.begin(), reldates.end(),
384 [str](
auto rel) ->
bool 386 return strcmp(str, rel.m_storage) == 0;
388 return per != reldates.end() ? per->m_period : RelativeDatePeriod::ABSOLUTE;
394 auto rdate{checked_reldate(per)};
395 return per == RelativeDatePeriod::START_PREV_YEAR ||
396 per == RelativeDatePeriod::END_PREV_YEAR ||
397 per == RelativeDatePeriod::START_PREV_QUARTER ||
398 per == RelativeDatePeriod::END_PREV_QUARTER ||
399 per == RelativeDatePeriod::START_PREV_MONTH ||
400 per == RelativeDatePeriod::END_PREV_MONTH ||
401 rdate.m_type == LAST;
407 auto rdate{checked_reldate(per)};
408 return per == RelativeDatePeriod::START_NEXT_YEAR ||
409 per == RelativeDatePeriod::END_NEXT_YEAR ||
410 per == RelativeDatePeriod::START_NEXT_QUARTER ||
411 per == RelativeDatePeriod::END_NEXT_QUARTER ||
412 per == RelativeDatePeriod::START_NEXT_MONTH ||
413 per == RelativeDatePeriod::END_NEXT_MONTH ||
414 rdate.m_type == NEXT;
417 static RelativeDateOffset
420 return checked_reldate(per).m_offset;
424 days_in_month(
int month,
int year)
434 normalize_reldate_tm(
struct tm& now)
436 auto delta = (now.tm_mon / 12) + (now.tm_mon < 0 ? -1 : 0);
437 now.tm_mon -= 12 * delta;
438 now.tm_year += delta;
444 if (now.tm_mon-- == 0)
449 now.tm_mday += days_in_month(now.tm_mon, now.tm_year);
450 }
while (now.tm_mday < 1) ;
454 while (now.tm_mday > (delta = days_in_month(now.tm_mon, now.tm_year)))
456 if (now.tm_mon++ == 11)
461 now.tm_mday -= delta;
466 reldate_set_day_and_time(
struct tm& now, RelativeDateType type)
468 if (type == RelativeDateType::START)
470 gnc_tm_set_day_start(&now);
473 else if (type == RelativeDateType::END)
476 auto year_delta = (now.tm_mon / 12) + (now.tm_mon < 0 ? -1 : 0);
477 auto month = now.tm_mon - (12 * year_delta);
478 auto year = now.tm_year + year_delta;
479 now.tm_mday = days_in_month(month, year);
480 gnc_tm_set_day_end(&now);
488 if (period == RelativeDatePeriod::TODAY)
490 if (period == RelativeDatePeriod::START_ACCOUNTING_PERIOD)
491 return gnc_accounting_period_fiscal_start();
492 if (period == RelativeDatePeriod::END_ACCOUNTING_PERIOD)
493 return gnc_accounting_period_fiscal_end();
496 if (period == RelativeDatePeriod::TODAY)
497 return static_cast<time64>(now_t);
498 auto now{
static_cast<tm
>(now_t)};
499 auto acct_per{
static_cast<tm
>(
GncDateTime(gnc_accounting_period_fiscal_start()))};
501 if (acct_per.tm_mon == now.tm_mon && acct_per.tm_mday == now.tm_mday)
505 acct_per.tm_mday = 0;
508 switch(reldate_offset(period))
510 case RelativeDateOffset::NONE:
513 case RelativeDateOffset::YEAR:
514 if (reldate_is_prev(period))
516 else if (reldate_is_next(period))
523 case RelativeDateOffset::SIX:
524 if (reldate_is_prev(period))
526 else if (reldate_is_next(period))
529 case RelativeDateOffset::QUARTER:
531 auto delta = (now.tm_mon > acct_per.tm_mon ?
532 ( now.tm_mon - acct_per.tm_mon) % 3 :
533 3 - ((acct_per.tm_mon - now.tm_mon) % 3));
534 now.tm_mon = now.tm_mon - delta;
537 case RelativeDateOffset::THREE:
538 if (reldate_is_prev(period))
540 else if (reldate_is_next(period))
545 case RelativeDateOffset::MONTH:
546 if (reldate_is_prev(period))
548 else if (reldate_is_next(period))
551 case RelativeDateOffset::WEEK:
552 if (reldate_is_prev(period))
554 else if (reldate_is_next(period))
557 reldate_set_day_and_time(now, checked_reldate(period).m_type);
558 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.
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.