Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add fortnightly interval #1955

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions frontend/src/format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ export const dateFormat: Record<Interval, DateFormatter> = {
quarter: (date) =>
`${date.getUTCFullYear().toString()}Q${(Math.floor(date.getUTCMonth() / 3) + 1).toString()}`,
month: utcFormat("%b %Y"),
fortnight: (date) => {
const year = Number.parseInt(utcFormat("%G")(date));
const week = Number.parseInt(utcFormat("%V")(date));
const [w1, w2] = week % 2 === 0 ? [week - 1, week] : [week, week + 1];
return `${year.toString()}W${w1.toString().padStart(2, "0")}/${w2.toString().padStart(2, "0")}`;
},
week: utcFormat("%YW%W"),
day,
};
Expand All @@ -61,6 +67,12 @@ export const timeFilterDateFormat: Record<Interval, DateFormatter> = {
quarter: (date) =>
`${date.getUTCFullYear().toString()}-Q${(Math.floor(date.getUTCMonth() / 3) + 1).toString()}`,
month: utcFormat("%Y-%m"),
fortnight: (date) => {
const year = Number.parseInt(utcFormat("%G")(date));
const week = Number.parseInt(utcFormat("%V")(date));
const [w1, w2] = week % 2 === 0 ? [week - 1, week] : [week, week + 1];
return `${year.toString()}-W${w1.toString().padStart(2, "0")}/${w2.toString().padStart(2, "0")}`;
},
week: utcFormat("%Y-W%W"),
day,
};
Expand Down
10 changes: 9 additions & 1 deletion frontend/src/lib/interval.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import { _ } from "../i18n";

export type Interval = "year" | "quarter" | "month" | "week" | "day";
export type Interval =
| "year"
| "quarter"
| "month"
| "fortnight"
| "week"
| "day";

export const DEFAULT_INTERVAL: Interval = "month";

export const INTERVALS: Interval[] = [
"year",
"quarter",
"month",
"fortnight",
"week",
"day",
];
Expand All @@ -22,6 +29,7 @@ export function intervalLabel(s: Interval): string {
year: _("Yearly"),
quarter: _("Quarterly"),
month: _("Monthly"),
fortnight: _("Fortnightly"),
week: _("Weekly"),
day: _("Daily"),
}[s];
Expand Down
17 changes: 11 additions & 6 deletions frontend/test/format.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,33 +29,38 @@ test("locale number formatting", () => {
});

test("time filter date formatting", () => {
const { day, month, week, quarter, year, ...rest } = timeFilterDateFormat;
const { day, week, fortnight, month, quarter, year, ...rest } =
timeFilterDateFormat;
assert.equal(rest, {});
const janfirst = new Date("2020-01-01");
const date = new Date("2020-03-20");
assert.is(day(janfirst), "2020-01-01");
assert.is(day(date), "2020-03-20");
assert.is(month(janfirst), "2020-01");
assert.is(month(date), "2020-03");
assert.is(week(janfirst), "2020-W00");
assert.is(week(date), "2020-W11");
assert.is(fortnight(janfirst), "2020-W01/02");
assert.is(fortnight(date), "2020-W11/12");
assert.is(month(janfirst), "2020-01");
assert.is(month(date), "2020-03");
assert.is(quarter(janfirst), "2020-Q1");
assert.is(quarter(date), "2020-Q1");
assert.is(year(janfirst), "2020");
assert.is(year(date), "2020");
});

test("human-readable date formatting", () => {
const { day, month, week, quarter, year, ...rest } = dateFormat;
const { day, week, fortnight, month, quarter, year, ...rest } = dateFormat;
assert.equal(rest, {});
const janfirst = new Date("2020-01-01");
const date = new Date("2020-03-20");
assert.is(day(janfirst), "2020-01-01");
assert.is(day(date), "2020-03-20");
assert.is(month(janfirst), "Jan 2020");
assert.is(month(date), "Mar 2020");
assert.is(week(janfirst), "2020W00");
assert.is(week(date), "2020W11");
assert.is(fortnight(janfirst), "2020W01/02");
assert.is(fortnight(date), "2020W11/12");
assert.is(month(janfirst), "Jan 2020");
assert.is(month(date), "Mar 2020");
assert.is(quarter(janfirst), "2020Q1");
assert.is(quarter(date), "2020Q1");
assert.is(year(janfirst), "2020");
Expand Down
1 change: 1 addition & 0 deletions src/fava/core/budgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ def parse_budgets(
interval_map = {
"daily": Interval.DAY,
"weekly": Interval.WEEK,
"fortnightly": Interval.FORTNIGHT,
"monthly": Interval.MONTH,
"quarterly": Interval.QUARTER,
"yearly": Interval.YEAR,
Expand Down
40 changes: 34 additions & 6 deletions src/fava/help/budgets.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,48 @@ Beancount file:
<pre><textarea is="beancount-textarea">
2012-01-01 custom "budget" Expenses:Coffee "daily" 4.00 EUR
2013-01-01 custom "budget" Expenses:Books "weekly" 20.00 EUR
2013-01-01 custom "budget" Expenses:Fuel "fortnightly" 60.00 EUR
2014-02-10 custom "budget" Expenses:Groceries "monthly" 40.00 EUR
2015-05-01 custom "budget" Expenses:Electricity "quarterly" 85.00 EUR
2016-06-01 custom "budget" Expenses:Holiday "yearly" 2500.00 EUR</textarea></pre>

If budgets are specified, Fava's reports and charts will display remaining
budgets and related information.

The budget directives can be specified `daily`, `weekly`, `monthly`, `quarterly`
and `yearly`. The specified budget is valid until another budget directive for
the account is specified. The budget is broken down to a daily budget, and
summed up for a range of dates as needed.
Each budget directive has an accunt for which the budget is specified, a
frequency and amount of the budget, and a date from which the budget is valid. A
budget directive remains valid until another budget directive for the account is
specified. For example:

This makes the budgets very flexible, allowing for a monthly budget, being taken
over by a weekly budget, and so on.
<pre><textarea is="beancount-textarea">
2012-01-01 custom "budget" Expenses:Coffee "daily" 4.00 EUR
2013-01-01 custom "budget" Expenses:Coffee "daily" 5.00 EUR
2014-01-01 custom "budget" Expenses:Coffee "weekly" 6.00 EUR</textarea></pre>

In this example, the coffee budget is 4.00 EUR for 2012, then increases to 5.00
EUR in 2013, and finally to 30 EUR per week in 2014.

Fava supports the following frequencies for the budget:

- `daily`
- `weekly`
- The week align with ISO weeks, and start on Monday.
- `fortnightly`
- Note that there are no standard conventions for dividing a year into
fortnights, and as such, Fava uses the following:
- The fortnight align with ISO weeks, with the first fortnight being W01 and
W02 of the year.
- For a year with 53 weeks, the last fortnight is W53 and W54 (equivalent to
the next year's W01). This unfortunately does result in overlapping
fortnights once every 7 years approximately.
- `monthly`
- This is the calendar month, and Fava internally uses the number of days in
each month to calculate the monthly budget. As a result, February with 28
days will have a lower budget than January with 31 days.
- `quarterly`
- Based on the calendar quarter, with the quarters starting on January 1,
April 1, July 1, and October 1.
- `yearly`

Fava displays budgets in both charts and reports. You can find a visualization
of the global budget in the `Net Profit` and `Expenses` charts for the Income
Expand Down
5 changes: 4 additions & 1 deletion src/fava/translations/bg/LC_MESSAGES/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,10 @@ msgstr "Тримесечен"
msgid "Monthly"
msgstr "Месечен"

#: frontend/src/lib/interval.ts:25 src/fava/util/date.py:105
msgid "Fortnightly"
msgstr "На всеки две седмици"

#: frontend/src/lib/interval.ts:25 src/fava/util/date.py:105
msgid "Weekly"
msgstr "Седмичен"
Expand Down Expand Up @@ -592,4 +596,3 @@ msgstr "Изтриване..."
#: frontend/src/sidebar/AsideContents.svelte:60
msgid "Add Journal Entry"
msgstr ""

5 changes: 4 additions & 1 deletion src/fava/translations/ca/LC_MESSAGES/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,10 @@ msgstr "Per trimestre"
msgid "Monthly"
msgstr "Per mes"

#: frontend/src/lib/interval.ts:25 src/fava/util/date.py:105
msgid "Fortnightly"
msgstr "Per quinzena"

#: frontend/src/lib/interval.ts:25 src/fava/util/date.py:105
msgid "Weekly"
msgstr "Per setmana"
Expand Down Expand Up @@ -592,4 +596,3 @@ msgstr "S'està suprimint..."
#: frontend/src/sidebar/AsideContents.svelte:60
msgid "Add Journal Entry"
msgstr ""

5 changes: 4 additions & 1 deletion src/fava/translations/de/LC_MESSAGES/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,10 @@ msgstr "Quartalsweise"
msgid "Monthly"
msgstr "Monatlich"

#: frontend/src/lib/interval.ts:25 src/fava/util/date.py:105
msgid "Fortnightly"
msgstr "Zweiwöchentlich"

#: frontend/src/lib/interval.ts:25 src/fava/util/date.py:105
msgid "Weekly"
msgstr "Wöchentlich"
Expand Down Expand Up @@ -592,4 +596,3 @@ msgstr "Wird gelöscht..."
#: frontend/src/sidebar/AsideContents.svelte:60
msgid "Add Journal Entry"
msgstr "Journal-Eintrag hinzufügen"

5 changes: 4 additions & 1 deletion src/fava/translations/fa/LC_MESSAGES/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,10 @@ msgstr "سه‌ماهه"
msgid "Monthly"
msgstr "ماهانه"

#: frontend/src/lib/interval.ts:25 src/fava/util/date.py:105
msgid "Fortnightly"
msgstr "هر دو هفته یکبار"

#: frontend/src/lib/interval.ts:25 src/fava/util/date.py:105
msgid "Weekly"
msgstr "هفتگی"
Expand Down Expand Up @@ -592,4 +596,3 @@ msgstr ""
#: frontend/src/sidebar/AsideContents.svelte:60
msgid "Add Journal Entry"
msgstr ""

5 changes: 4 additions & 1 deletion src/fava/translations/fr/LC_MESSAGES/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,10 @@ msgstr "Trimestriel"
msgid "Monthly"
msgstr "Mensuel"

#: frontend/src/lib/interval.ts:25 src/fava/util/date.py:105
msgid "Fortnightly"
msgstr "Bimensuel"

#: frontend/src/lib/interval.ts:25 src/fava/util/date.py:105
msgid "Weekly"
msgstr "Hebdomadaire"
Expand Down Expand Up @@ -592,4 +596,3 @@ msgstr "Suppression..."
#: frontend/src/sidebar/AsideContents.svelte:60
msgid "Add Journal Entry"
msgstr ""

5 changes: 4 additions & 1 deletion src/fava/translations/nl/LC_MESSAGES/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,10 @@ msgstr "Per kwartaal"
msgid "Monthly"
msgstr "Maandelijks"

#: frontend/src/lib/interval.ts:25 src/fava/util/date.py:105
msgid "Fortnightly"
msgstr "Tweewekelijks"

#: frontend/src/lib/interval.ts:25 src/fava/util/date.py:105
msgid "Weekly"
msgstr "Wekelijks"
Expand Down Expand Up @@ -592,4 +596,3 @@ msgstr ""
#: frontend/src/sidebar/AsideContents.svelte:60
msgid "Add Journal Entry"
msgstr ""

5 changes: 4 additions & 1 deletion src/fava/translations/pt_BR/LC_MESSAGES/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,10 @@ msgstr "Trimestral"
msgid "Monthly"
msgstr "Mensal"

#: frontend/src/lib/interval.ts:25 src/fava/util/date.py:105
msgid "Fortnightly"
msgstr "Quinzenal"

#: frontend/src/lib/interval.ts:25 src/fava/util/date.py:105
msgid "Weekly"
msgstr "Semanal"
Expand Down Expand Up @@ -593,4 +597,3 @@ msgstr "Apagando..."
#: frontend/src/sidebar/AsideContents.svelte:60
msgid "Add Journal Entry"
msgstr "Adicionar Entrada"

5 changes: 4 additions & 1 deletion src/fava/translations/ru/LC_MESSAGES/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,10 @@ msgstr "По кварталам"
msgid "Monthly"
msgstr "По месяцам"

#: frontend/src/lib/interval.ts:25 src/fava/util/date.py:105
msgid "Fortnightly"
msgstr "Каждые две недели"

#: frontend/src/lib/interval.ts:25 src/fava/util/date.py:105
msgid "Weekly"
msgstr "По неделям"
Expand Down Expand Up @@ -591,4 +595,3 @@ msgstr ""
#: frontend/src/sidebar/AsideContents.svelte:60
msgid "Add Journal Entry"
msgstr ""

5 changes: 4 additions & 1 deletion src/fava/translations/sk/LC_MESSAGES/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,10 @@ msgstr "Kvartálne"
msgid "Monthly"
msgstr "Mesačne"

#: frontend/src/lib/interval.ts:25 src/fava/util/date.py:105
msgid "Fortnightly"
msgstr "Dvotýždenne"

#: frontend/src/lib/interval.ts:25 src/fava/util/date.py:105
msgid "Weekly"
msgstr "Týždenne"
Expand Down Expand Up @@ -597,4 +601,3 @@ msgstr ""
#: frontend/src/sidebar/AsideContents.svelte:60
msgid "Add Journal Entry"
msgstr ""

5 changes: 4 additions & 1 deletion src/fava/translations/sv/LC_MESSAGES/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,10 @@ msgstr "Kvartalsvis"
msgid "Monthly"
msgstr "Månatligt"

#: frontend/src/lib/interval.ts:25 src/fava/util/date.py:105
msgid "Fortnightly"
msgstr "Var fjortonde dag"

#: frontend/src/lib/interval.ts:25 src/fava/util/date.py:105
msgid "Weekly"
msgstr "Veckovis"
Expand Down Expand Up @@ -592,4 +596,3 @@ msgstr ""
#: frontend/src/sidebar/AsideContents.svelte:60
msgid "Add Journal Entry"
msgstr ""

5 changes: 4 additions & 1 deletion src/fava/translations/uk/LC_MESSAGES/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,10 @@ msgstr "Щоквартально"
msgid "Monthly"
msgstr "Щомісячно"

#: frontend/src/lib/interval.ts:25 src/fava/util/date.py:105
msgid "Fortnightly"
msgstr "двотижневий"

#: frontend/src/lib/interval.ts:25 src/fava/util/date.py:105
msgid "Weekly"
msgstr "Щотижнево"
Expand Down Expand Up @@ -592,4 +596,3 @@ msgstr ""
#: frontend/src/sidebar/AsideContents.svelte:60
msgid "Add Journal Entry"
msgstr ""

5 changes: 4 additions & 1 deletion src/fava/translations/zh/LC_MESSAGES/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,10 @@ msgstr "按季"
msgid "Monthly"
msgstr "按月"

#: frontend/src/lib/interval.ts:25 src/fava/util/date.py:105
msgid "Fortnightly"
msgstr "按两周"

#: frontend/src/lib/interval.ts:25 src/fava/util/date.py:105
msgid "Weekly"
msgstr "按周"
Expand Down Expand Up @@ -592,4 +596,3 @@ msgstr "正在删除..."
#: frontend/src/sidebar/AsideContents.svelte:60
msgid "Add Journal Entry"
msgstr "添加日记账条目"

5 changes: 4 additions & 1 deletion src/fava/translations/zh_Hant_TW/LC_MESSAGES/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,10 @@ msgstr "季度"
msgid "Monthly"
msgstr "月"

#: frontend/src/lib/interval.ts:25 src/fava/util/date.py:105
msgid "Fortnightly"
msgstr "兩周"

#: frontend/src/lib/interval.ts:25 src/fava/util/date.py:105
msgid "Weekly"
msgstr "週"
Expand Down Expand Up @@ -594,4 +598,3 @@ msgstr "正在删除..."
#: frontend/src/sidebar/AsideContents.svelte:60
msgid "Add Journal Entry"
msgstr ""

Loading