@fin.cx/opendata 4.5.0 → 4.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/cpi/classes.bundesbankcpiclient.js +1 -1
- package/dist_ts/cpi/classes.cpierror.js +1 -1
- package/dist_ts/cpi/constants.d.ts +2 -2
- package/dist_ts/cpi/indexmath.js +1 -1
- package/dist_ts/handelsregister/classes.handelsregisterclient.js +1 -1
- package/dist_ts/handelsregister/classes.handelsregistererror.js +1 -1
- package/dist_ts/handelsregister/classes.portalsession.js +1 -1
- package/dist_ts/handelsregister/classes.slidingwindowgate.js +1 -1
- package/dist_ts/handelsregister/parse.searchresults.js +1 -1
- package/dist_ts/handelsregister/references.js +1 -1
- package/dist_ts/holidays/calendar.d.ts +13 -1
- package/dist_ts/holidays/calendar.js +52 -1
- package/dist_ts/holidays/classes.holidaycalendarerror.d.ts +4 -1
- package/dist_ts/holidays/classes.holidaycalendarerror.js +1 -1
- package/dist_ts/holidays/data.holidays.js +1 -1
- package/dist_ts/holidays/index.d.ts +1 -1
- package/dist_ts/holidays/index.js +2 -2
- package/dist_ts/holidays/interfaces.d.ts +2 -0
- package/dist_ts/paths.js +1 -1
- package/dist_ts/stocks/providers/provider.coingecko.js +1 -1
- package/dist_ts/stocks/providers/provider.marketstack.js +1 -1
- package/dist_ts/stocks/providers/provider.yahoo.js +1 -1
- package/dist_ts/vatid/classes.evatrclient.js +1 -1
- package/dist_ts/vatid/classes.viesclient.js +1 -1
- package/dist_ts/vatid/constants.d.ts +2 -2
- package/dist_ts/vatid/request.d.ts +1 -1
- package/package.json +3 -3
- package/readme.md +26 -2
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/holidays/calendar.ts +73 -0
- package/ts/holidays/classes.holidaycalendarerror.ts +10 -1
- package/ts/holidays/index.ts +2 -0
- package/ts/holidays/interfaces.ts +3 -0
package/readme.md
CHANGED
|
@@ -7,7 +7,7 @@ It gives you seven practical lanes in one package:
|
|
|
7
7
|
- `StockPriceService` for stock and crypto prices with caching, retries, failover, historical ranges, and intraday support
|
|
8
8
|
- `FundamentalsService` and `StockDataService` for SEC fundamentals and combined price + fundamentals payloads
|
|
9
9
|
- `HandelsregisterClient`, from `@fin.cx/opendata/handelsregister`, for single lookups in the commercial, cooperative, partnership, association and civil-law partnership registers over plain HTTP, without any storage
|
|
10
|
-
- the holiday calendar, from `@fin.cx/opendata/holidays`, for the statutory public holidays of each German federal state
|
|
10
|
+
- the holiday calendar, from `@fin.cx/opendata/holidays`, for the statutory public holidays of each German federal state, the working days of § 193 BGB and the bank working days the social insurance counts its due dates in, computed per year without data files or requests
|
|
11
11
|
- the base rate, from `@fin.cx/opendata/baserate`, for the Basiszinssatz of § 247 BGB per half-year as the Deutsche Bundesbank publishes it, for default interest under § 288 BGB
|
|
12
12
|
- VAT ID confirmation, from `@fin.cx/opendata/vatid`, over the BZSt's eVatR REST API (the confirmation of § 18e UStG, simple or qualified) and the European Commission's VIES REST API, without any storage
|
|
13
13
|
- the consumer price index, from `@fin.cx/opendata/cpi`, for the Verbraucherpreisindex für Deutschland of the Statistisches Bundesamt as the Deutsche Bundesbank republishes it, with the arithmetic of index clauses (Wertsicherungsklauseln, § 557b BGB), without any storage
|
|
@@ -60,6 +60,8 @@ Everything here comes from `@fin.cx/opendata/holidays`. That entry point imports
|
|
|
60
60
|
The statutory public holidays of a federal state in a year or on a date, each with its legal basis.
|
|
61
61
|
- `isPublicHoliday()`, `isWorkingDay()`, `nextWorkingDay()`, `workingDayOnOrAfter()`
|
|
62
62
|
Holidays and working days in the sense of § 193 BGB: neither a Saturday, nor a Sunday, nor a statutory public holiday.
|
|
63
|
+
- `isBankWorkingDay()`, `nthLastBankWorkingDay()`
|
|
64
|
+
Bank working days (Bankarbeitstage), which also leave out 24 and 31 December, when the Deutsche Bundesbank is closed: the days German social insurance due dates are counted in.
|
|
63
65
|
- `easterSunday(year)`, `germanStates`, `findGermanState()`
|
|
64
66
|
|
|
65
67
|
### The Base Rate Of § 247 BGB
|
|
@@ -468,6 +470,24 @@ workingDayOnOrAfter('2026-05-14', 'DE-BY', { regionalHolidays: 'ignore' }); // '
|
|
|
468
470
|
|
|
469
471
|
States are ISO 3166-2 codes (`DE-BY`); `findGermanState('Bayern')` and `findGermanState('BY')` find one. Dates are plain calendar dates written `YYYY-MM-DD`, so no time zone can move them.
|
|
470
472
|
|
|
473
|
+
#### Bank working days
|
|
474
|
+
|
|
475
|
+
A bank working day (Bankarbeitstag) is neither a Saturday, nor a Sunday, nor a statutory public holiday, nor 24 or 31 December. On those two days the Deutsche Bundesbank is closed although they are no statutory holidays; its list of holidays names them as its additional closing days. German social insurance counts its due dates in these days, with the holidays of the state where the collecting agency (Einzugsstelle) has its seat: contributions are due on the third-last bank working day of the month, and the contribution statement has to be with the collecting agency at the start of the fifth-last.
|
|
476
|
+
|
|
477
|
+
```ts
|
|
478
|
+
import { isBankWorkingDay, nthLastBankWorkingDay } from '@fin.cx/opendata/holidays';
|
|
479
|
+
|
|
480
|
+
isBankWorkingDay('2026-12-24', 'DE-HH', { regionalHolidays: 'ignore' }); // false: the Bundesbank is closed
|
|
481
|
+
nthLastBankWorkingDay('2026-12', 3, 'DE-HH', { regionalHolidays: 'ignore' }); // '2026-12-28'
|
|
482
|
+
nthLastBankWorkingDay('2026-12', 5, 'DE-HH', { regionalHolidays: 'ignore' }); // '2026-12-22'
|
|
483
|
+
|
|
484
|
+
// Reformationstag 2025 was a Friday: a holiday in Niedersachsen, a working day in Bayern
|
|
485
|
+
nthLastBankWorkingDay('2025-10', 3, 'DE-NI', { regionalHolidays: 'ignore' }); // '2025-10-28'
|
|
486
|
+
nthLastBankWorkingDay('2025-10', 3, 'DE-BY', { regionalHolidays: 'ignore' }); // '2025-10-29'
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
Months are written `YYYY-MM`. The position counts from the end of the month, 1 being the last bank working day; a position the month does not have ends in `invalid_position`. The tests hold the results against the due dates the collecting agencies published for 2025 and 2026.
|
|
490
|
+
|
|
471
491
|
#### Regional holidays
|
|
472
492
|
|
|
473
493
|
Four holidays apply only in part of a state:
|
|
@@ -563,10 +583,12 @@ Four holidays apply only in part of a state:
|
|
|
563
583
|
- `isWorkingDay(date, state, { regionalHolidays })`
|
|
564
584
|
- `nextWorkingDay(date, state, { regionalHolidays })`
|
|
565
585
|
- `workingDayOnOrAfter(date, state, { regionalHolidays })`
|
|
586
|
+
- `isBankWorkingDay(date, state, { regionalHolidays })`
|
|
587
|
+
- `nthLastBankWorkingDay(month, position, state, { regionalHolidays })`
|
|
566
588
|
- `easterSunday(year)`
|
|
567
589
|
- `germanStates`, `findGermanState(codeOrName)`
|
|
568
590
|
- `holidayCalendarFirstYear`, `holidayLawsReadOn`
|
|
569
|
-
- `HolidayCalendarError` with the codes `invalid_date`, `unsupported_year`, `unknown_state` and `invalid_options`
|
|
591
|
+
- `HolidayCalendarError` with the codes `invalid_date`, `invalid_month`, `invalid_position`, `unsupported_year`, `unknown_state` and `invalid_options`
|
|
570
592
|
|
|
571
593
|
### VAT ID (`@fin.cx/opendata/vatid`)
|
|
572
594
|
|
|
@@ -635,6 +657,8 @@ The holiday calendar is derived from the holiday laws of the federal states, rea
|
|
|
635
657
|
| Thüringen | [Thüringer Feier- und Gedenktagsgesetz (ThürFGtG)](https://landesrecht.thueringen.de/perma?j=FeiertG_TH_!_2) | § 2, § 10 Abs. 1 |
|
|
636
658
|
| all | [Bürgerliches Gesetzbuch](https://www.gesetze-im-internet.de/bgb/__193.html) | § 193 (Sonntag, Feiertag, Sonnabend) |
|
|
637
659
|
|
|
660
|
+
The bank working days follow the Deutsche Bundesbank's list "Feiertage in Deutschland im Jahr 2026", read on 2026-10-08, which names 24 December (Heiligabend) and 31 December (Silvester) as its additional closing days ("Zusätzliche geschäftsfreie Tage der Deutschen Bundesbank"), and the collecting agencies' statement that these two days are no bank working days for the due dates of contributions, that a holiday counts by the seat of the collecting agency, and their published due dates of 2025 (AOK, with separate October dates for the states with and without Reformationstag) and 2026 (TK, AOK and KKH). The calendar takes the two closing days as fixed; a change of the Bundesbank's closing days needs a new version.
|
|
661
|
+
|
|
638
662
|
The base rate of `@fin.cx/opendata/baserate` (`ts/baserate/data.baserate.ts`) is the table "Basiszinssatz nach § 247 BGB" of the Deutsche Bundesbank (https://www.bundesbank.de/de/bundesbank/organisation/agb-und-regelungen/basiszinssatz-607820), which the Bundesbank publishes under § 247 Abs. 2 BGB, read on 2026-09-27 and reproduced unaltered: every half-year from 1 July 2002, the first row it lists, to the half-year from 1 July 2026 (1,52 %). The rate changes on 1 January and 1 July (§ 247 Abs. 1 Satz 2 BGB); a day after 31 December 2026 answers `not_published` until a release carries the next row.
|
|
639
663
|
|
|
640
664
|
The VAT ID clients of `@fin.cx/opendata/vatid` ask two official services at run time, one request at a time, read on 2026-09-27:
|
package/ts/00_commitinfo_data.ts
CHANGED
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@fin.cx/opendata',
|
|
6
|
-
version: '4.
|
|
6
|
+
version: '4.6.0',
|
|
7
7
|
description: 'Open business and financial data for TypeScript: register lookups on the German register portal (handelsregister.de) without storage, the statutory public holidays of the German federal states, the base rate of § 247 BGB, the German consumer price index with the arithmetic of index clauses, and stock and crypto prices and fundamentals from several providers.'
|
|
8
8
|
}
|
package/ts/holidays/calendar.ts
CHANGED
|
@@ -7,6 +7,7 @@ import type {
|
|
|
7
7
|
IWorkingDayOptions,
|
|
8
8
|
TGermanStateCode,
|
|
9
9
|
TIsoDate,
|
|
10
|
+
TIsoMonth,
|
|
10
11
|
} from './interfaces.js';
|
|
11
12
|
|
|
12
13
|
const dayMs = 86_400_000;
|
|
@@ -57,6 +58,17 @@ const parseIsoDate = (dateArg: TIsoDate): ICalendarDay => {
|
|
|
57
58
|
return { year, utc };
|
|
58
59
|
};
|
|
59
60
|
|
|
61
|
+
const parseIsoMonth = (monthArg: TIsoMonth): { year: number; month: number } => {
|
|
62
|
+
const match = typeof monthArg === 'string' ? /^(\d{4})-(\d{2})$/.exec(monthArg) : null;
|
|
63
|
+
const month = match ? Number(match[2]) : 0;
|
|
64
|
+
if (!match || month < 1 || month > 12) {
|
|
65
|
+
throw new HolidayCalendarError('invalid_month', `A month is written YYYY-MM; ${JSON.stringify(monthArg)} is not.`);
|
|
66
|
+
}
|
|
67
|
+
const year = Number(match[1]);
|
|
68
|
+
checkYear(year);
|
|
69
|
+
return { year, month };
|
|
70
|
+
};
|
|
71
|
+
|
|
60
72
|
const checkState = (stateArg: TGermanStateCode): void => {
|
|
61
73
|
if (!germanStates.some((stateEntry) => stateEntry.code === stateArg)) {
|
|
62
74
|
throw new HolidayCalendarError(
|
|
@@ -189,6 +201,15 @@ const isWorkingDayUtc = (utcArg: number, stateArg: TGermanStateCode, optionsArg:
|
|
|
189
201
|
return weekday !== 0 && weekday !== 6 && !isHolidayUtc(utcArg, stateArg, optionsArg);
|
|
190
202
|
};
|
|
191
203
|
|
|
204
|
+
/** 24 and 31 December, the days the Deutsche Bundesbank closes besides the statutory holidays */
|
|
205
|
+
const isBundesbankClosingDayUtc = (utcArg: number): boolean => {
|
|
206
|
+
const date = new Date(utcArg);
|
|
207
|
+
return date.getUTCMonth() === 11 && (date.getUTCDate() === 24 || date.getUTCDate() === 31);
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
const isBankWorkingDayUtc = (utcArg: number, stateArg: TGermanStateCode, optionsArg: IWorkingDayOptions): boolean =>
|
|
211
|
+
isWorkingDayUtc(utcArg, stateArg, optionsArg) && !isBundesbankClosingDayUtc(utcArg);
|
|
212
|
+
|
|
192
213
|
/** Whether a date is a statutory public holiday in a state. */
|
|
193
214
|
export const isPublicHoliday = (
|
|
194
215
|
dateArg: TIsoDate,
|
|
@@ -212,6 +233,58 @@ export const isWorkingDay = (dateArg: TIsoDate, stateArg: TGermanStateCode, opti
|
|
|
212
233
|
return isWorkingDayUtc(day.utc, stateArg, optionsArg);
|
|
213
234
|
};
|
|
214
235
|
|
|
236
|
+
/**
|
|
237
|
+
* Whether a date is a bank working day (Bankarbeitstag) in a state: neither a Saturday, nor a
|
|
238
|
+
* Sunday, nor a statutory public holiday, nor 24 or 31 December, on which the Deutsche Bundesbank
|
|
239
|
+
* is closed. These are the days the German social insurance counts the due dates of contributions
|
|
240
|
+
* in, with the holidays of the state where the collecting agency has its seat.
|
|
241
|
+
*/
|
|
242
|
+
export const isBankWorkingDay = (
|
|
243
|
+
dateArg: TIsoDate,
|
|
244
|
+
stateArg: TGermanStateCode,
|
|
245
|
+
optionsArg: IWorkingDayOptions,
|
|
246
|
+
): boolean => {
|
|
247
|
+
const day = parseIsoDate(dateArg);
|
|
248
|
+
checkState(stateArg);
|
|
249
|
+
checkOptions(optionsArg);
|
|
250
|
+
return isBankWorkingDayUtc(day.utc, stateArg, optionsArg);
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* The bank working day of a month at a position counted from the month's end: 1 is the last bank
|
|
255
|
+
* working day of the month, 3 the third-last.
|
|
256
|
+
*/
|
|
257
|
+
export const nthLastBankWorkingDay = (
|
|
258
|
+
monthArg: TIsoMonth,
|
|
259
|
+
positionArg: number,
|
|
260
|
+
stateArg: TGermanStateCode,
|
|
261
|
+
optionsArg: IWorkingDayOptions,
|
|
262
|
+
): TIsoDate => {
|
|
263
|
+
const { year, month } = parseIsoMonth(monthArg);
|
|
264
|
+
checkState(stateArg);
|
|
265
|
+
checkOptions(optionsArg);
|
|
266
|
+
if (!Number.isInteger(positionArg) || positionArg < 1) {
|
|
267
|
+
throw new HolidayCalendarError(
|
|
268
|
+
'invalid_position',
|
|
269
|
+
`A position counted from the end of a month is a whole number from 1 on, not ${String(positionArg)}.`,
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
const first = utcOf(year, month, 1);
|
|
273
|
+
let found = 0;
|
|
274
|
+
for (let utc = utcOf(year, month + 1, 0); utc >= first; utc -= dayMs) {
|
|
275
|
+
if (isBankWorkingDayUtc(utc, stateArg, optionsArg)) {
|
|
276
|
+
found += 1;
|
|
277
|
+
if (found === positionArg) {
|
|
278
|
+
return toIsoDate(utc);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
throw new HolidayCalendarError(
|
|
283
|
+
'invalid_position',
|
|
284
|
+
`${monthArg} has ${found} bank working days in ${stateArg}, fewer than ${positionArg}.`,
|
|
285
|
+
);
|
|
286
|
+
};
|
|
287
|
+
|
|
215
288
|
/** The first working day after a date (§ 193 BGB: not a Saturday, Sunday or public holiday). */
|
|
216
289
|
export const nextWorkingDay = (dateArg: TIsoDate, stateArg: TGermanStateCode, optionsArg: IWorkingDayOptions): TIsoDate => {
|
|
217
290
|
const day = parseIsoDate(dateArg);
|
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Why a question to the holiday calendar was refused:
|
|
3
3
|
* - `invalid_date`: the value is not a calendar date written `YYYY-MM-DD`;
|
|
4
|
+
* - `invalid_month`: the value is not a calendar month written `YYYY-MM`;
|
|
5
|
+
* - `invalid_position`: the position of a bank working day counted from the end of a month is not
|
|
6
|
+
* a whole number from 1 up to the number of bank working days the month has;
|
|
4
7
|
* - `unsupported_year`: the year lies before the first year the calendar answers for (2018) or
|
|
5
8
|
* after 9999;
|
|
6
9
|
* - `unknown_state`: the value is not the code of a German federal state;
|
|
7
10
|
* - `invalid_options`: the options do not say how to treat regional holidays.
|
|
8
11
|
*/
|
|
9
|
-
export type THolidayCalendarErrorCode =
|
|
12
|
+
export type THolidayCalendarErrorCode =
|
|
13
|
+
| 'invalid_date'
|
|
14
|
+
| 'invalid_month'
|
|
15
|
+
| 'invalid_position'
|
|
16
|
+
| 'unsupported_year'
|
|
17
|
+
| 'unknown_state'
|
|
18
|
+
| 'invalid_options';
|
|
10
19
|
|
|
11
20
|
/** The typed error of the holiday calendar. */
|
|
12
21
|
export class HolidayCalendarError extends Error {
|
package/ts/holidays/index.ts
CHANGED
|
@@ -27,6 +27,9 @@ export interface IGermanState {
|
|
|
27
27
|
/** A plain calendar date, `YYYY-MM-DD`. */
|
|
28
28
|
export type TIsoDate = string;
|
|
29
29
|
|
|
30
|
+
/** A calendar month, `YYYY-MM`. */
|
|
31
|
+
export type TIsoMonth = string;
|
|
32
|
+
|
|
30
33
|
/** The statutory public holidays the calendar knows. */
|
|
31
34
|
export type TPublicHolidayId =
|
|
32
35
|
| 'neujahr'
|