UNPKG

react-financial-charts

Version:
189 lines 7.62 kB
import { timeFormat, timeFormatDefaultLocale } from "d3-time-format"; import { identity, isNotDefined, slidingWindow, zipper } from "../utils"; import financeDiscontinuousScale from "./financeDiscontinuousScale"; import { defaultFormatters, levelDefinition } from "./levels"; function evaluateLevel(d, date, i, formatters) { return levelDefinition .map((eachLevel, idx) => { return { level: levelDefinition.length - idx - 1, // @ts-ignore format: formatters[eachLevel(d, date, i)], }; }) .find((l) => !!l.format); } const discontinuousIndexCalculator = slidingWindow() .windowSize(2) .undefinedValue((d, idx, { initialIndex, formatters }) => { const i = initialIndex; const row = { date: d.getTime(), startOf30Seconds: false, startOfMinute: false, startOf5Minutes: false, startOf15Minutes: false, startOf30Minutes: false, startOfHour: false, startOfEighthOfADay: false, startOfQuarterDay: false, startOfHalfDay: false, startOfDay: true, startOfWeek: false, startOfMonth: false, startOfQuarter: false, startOfYear: false, }; const level = evaluateLevel(row, d, i, formatters); return Object.assign(Object.assign(Object.assign({}, row), { index: i }), level); }); const discontinuousIndexCalculatorLocalTime = discontinuousIndexCalculator .accumulator(([prevDate, nowDate], i, idx, { initialIndex, formatters }) => { const startOf30Seconds = nowDate.getSeconds() % 30 === 0; const startOfMinute = nowDate.getMinutes() !== prevDate.getMinutes(); const startOf5Minutes = startOfMinute && nowDate.getMinutes() % 5 <= prevDate.getMinutes() % 5; const startOf15Minutes = startOfMinute && nowDate.getMinutes() % 15 <= prevDate.getMinutes() % 15; const startOf30Minutes = startOfMinute && nowDate.getMinutes() % 30 <= prevDate.getMinutes() % 30; const startOfHour = nowDate.getHours() !== prevDate.getHours(); const startOfEighthOfADay = startOfHour && nowDate.getHours() % 3 === 0; const startOfQuarterDay = startOfHour && nowDate.getHours() % 6 === 0; const startOfHalfDay = startOfHour && nowDate.getHours() % 12 === 0; const startOfDay = nowDate.getDay() !== prevDate.getDay(); // According to ISO calendar // Sunday = 0, Monday = 1, ... Saturday = 6 // day of week of today < day of week of yesterday then today is start of week const startOfWeek = nowDate.getDay() < prevDate.getDay(); // month of today != month of yesterday then today is start of month const startOfMonth = nowDate.getMonth() !== prevDate.getMonth(); // if start of month and month % 3 === 0 then it is start of quarter const startOfQuarter = startOfMonth && (nowDate.getMonth() % 3 <= prevDate.getMonth() % 3); // year of today != year of yesterday then today is start of year const startOfYear = nowDate.getFullYear() !== prevDate.getFullYear(); const row = { date: nowDate.getTime(), startOf30Seconds, startOfMinute, startOf5Minutes, startOf15Minutes, startOf30Minutes, startOfHour, startOfEighthOfADay, startOfQuarterDay, startOfHalfDay, startOfDay, startOfWeek, startOfMonth, startOfQuarter, startOfYear, }; const level = evaluateLevel(row, nowDate, i, formatters); return Object.assign(Object.assign(Object.assign({}, row), { index: i + initialIndex }), level); }); function doStuff(realDateAccessor, inputDateAccessor, initialIndex, formatters) { return function (data) { const dateAccessor = realDateAccessor(inputDateAccessor); const calculate = discontinuousIndexCalculatorLocalTime .source(dateAccessor) .misc({ initialIndex, formatters }); const index = calculate(data).map((each) => { const { format } = each; return { // ...each, index: each.index, level: each.level, date: new Date(each.date), format: timeFormat(format), }; }); return { index }; }; } export function discontinuousTimeScaleProviderBuilder() { let initialIndex = 0; let realDateAccessor = identity; let inputDateAccessor = (d) => d.date; let indexAccessor = (d) => d.idx; let indexMutator = (d, idx) => (Object.assign(Object.assign({}, d), { idx })); let withIndex; let currentFormatters = defaultFormatters; const discontinuousTimeScaleProvider = function (data) { let index = withIndex; if (isNotDefined(index)) { const response = doStuff(realDateAccessor, inputDateAccessor, initialIndex, currentFormatters)(data); index = response.index; } const inputIndex = index; // @ts-ignore const xScale = financeDiscontinuousScale(inputIndex); const mergedData = zipper() .combine(indexMutator); // @ts-ignore const finalData = mergedData(data, inputIndex); return { data: finalData, xScale, xAccessor: (d) => d && indexAccessor(d).index, displayXAccessor: realDateAccessor(inputDateAccessor), }; }; discontinuousTimeScaleProvider.initialIndex = function (x) { if (!arguments.length) { return initialIndex; } initialIndex = x; return discontinuousTimeScaleProvider; }; discontinuousTimeScaleProvider.inputDateAccessor = function (x) { if (!arguments.length) { return inputDateAccessor; } inputDateAccessor = x; return discontinuousTimeScaleProvider; }; discontinuousTimeScaleProvider.indexAccessor = function (x) { if (!arguments.length) { return indexAccessor; } indexAccessor = x; return discontinuousTimeScaleProvider; }; discontinuousTimeScaleProvider.indexMutator = function (x) { if (!arguments.length) { return indexMutator; } indexMutator = x; return discontinuousTimeScaleProvider; }; discontinuousTimeScaleProvider.withIndex = function (x) { if (!arguments.length) { return withIndex; } withIndex = x; return discontinuousTimeScaleProvider; }; discontinuousTimeScaleProvider.utc = function () { realDateAccessor = (dateAccessor) => (d) => { const date = dateAccessor(d); // The getTimezoneOffset() method returns the time-zone offset from UTC, in minutes, for the current locale. const offsetInMillis = date.getTimezoneOffset() * 60 * 1000; return new Date(date.getTime() + offsetInMillis); }; return discontinuousTimeScaleProvider; }; discontinuousTimeScaleProvider.setLocale = function (locale, formatters = null) { if (locale) { timeFormatDefaultLocale(locale); } if (formatters) { // @ts-ignore currentFormatters = formatters; } return discontinuousTimeScaleProvider; }; discontinuousTimeScaleProvider.indexCalculator = function () { return doStuff(realDateAccessor, inputDateAccessor, initialIndex, currentFormatters); }; return discontinuousTimeScaleProvider; } export default discontinuousTimeScaleProviderBuilder(); //# sourceMappingURL=discontinuousTimeScaleProvider.js.map