add explicit type for string-based datetimes, replacing third-party datetime type with internal DateTime type

This commit is contained in:
MaysWind
2025-08-25 00:31:30 +08:00
parent f196ce969b
commit 25681f622d
35 changed files with 423 additions and 404 deletions
@@ -17,7 +17,7 @@ import type { TransactionReconciliationStatementResponseItem } from '@/models/tr
import { isDefined, isArray } from '@/lib/common.ts';
import { sumAmounts } from '@/lib/numeral.ts';
import {
getYearAndMonthFromUnixTime,
getGregorianCalendarYearAndMonthFromUnixTime,
getYearFirstUnixTimeBySpecifiedUnixTime,
getQuarterFirstUnixTimeBySpecifiedUnixTime,
getMonthFirstUnixTimeBySpecifiedUnixTime,
@@ -99,8 +99,8 @@ export function useAccountBalanceTrendsChartBase(props: CommonAccountBalanceTren
if (!isDefined(props.dateAggregationType)) {
return getAllDaysStartAndEndUnixTimes(dataDateRange.value.minUnixTime, dataDateRange.value.maxUnixTime);
} else {
const startYearMonth = getYearAndMonthFromUnixTime(dataDateRange.value.minUnixTime);
const endYearMonth = getYearAndMonthFromUnixTime(dataDateRange.value.maxUnixTime);
const startYearMonth = getGregorianCalendarYearAndMonthFromUnixTime(dataDateRange.value.minUnixTime);
const endYearMonth = getGregorianCalendarYearAndMonthFromUnixTime(dataDateRange.value.maxUnixTime);
return getAllDateRangesByYearMonthRange(startYearMonth, endYearMonth, props.fiscalYearStart, props.dateAggregationType);
}
});
+7 -10
View File
@@ -4,9 +4,9 @@ import { type TimeRangeAndDateType, type PresetDateRange, type UnixTimeRange, ty
import { arrangeArrayWithNewStartIndex } from '@/lib/common.ts';
import {
getCurrentUnixTime,
getCurrentYear,
getUnixTime,
getAllowedYearRange,
getLocalDatetimeFromUnixTime,
getUnixTimeFromLocalDatetime,
getTodayFirstUnixTime,
getDummyUnixTimeForLocalUsage,
getActualUnixTimeForStore,
@@ -50,10 +50,7 @@ export function useDateRangeSelectionBase(props: CommonDateRangeSelectionProps)
const userStore = useUserStore();
const { minDate, maxDate } = getDateRangeFromProps(props);
const yearRange = ref<number[]>([
2000,
getCurrentYear() + 1
]);
const yearRange = ref<number[]>(getAllowedYearRange());
const dateRange = ref<Date[]>([
getLocalDatetimeFromUnixTime(getDummyUnixTimeForLocalUsage(minDate, getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes())),
@@ -65,11 +62,11 @@ export function useDateRangeSelectionBase(props: CommonDateRangeSelectionProps)
const isYearFirst = computed<boolean>(() => isLongDateMonthAfterYear());
const is24Hour = computed<boolean>(() => isLongTime24HourFormat());
const beginDateTime = computed<string>(() => {
const actualBeginUnixTime = getActualUnixTimeForStore(getUnixTime(dateRange.value[0]), getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes());
const actualBeginUnixTime = getActualUnixTimeForStore(getUnixTimeFromLocalDatetime(dateRange.value[0]), getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes());
return formatUnixTimeToLongDateTime(actualBeginUnixTime);
});
const endDateTime = computed<string>(() => {
const actualEndUnixTime = getActualUnixTimeForStore(getUnixTime(dateRange.value[1]), getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes());
const actualEndUnixTime = getActualUnixTimeForStore(getUnixTimeFromLocalDatetime(dateRange.value[1]), getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes());
return formatUnixTimeToLongDateTime(actualEndUnixTime);
});
const presetRanges = computed<PresetDateRange[]>(() => {
@@ -108,8 +105,8 @@ export function useDateRangeSelectionBase(props: CommonDateRangeSelectionProps)
const currentMinDate = dateRange.value[0];
const currentMaxDate = dateRange.value[1];
let minUnixTime = getUnixTime(currentMinDate);
let maxUnixTime = getUnixTime(currentMaxDate);
let minUnixTime = getUnixTimeFromLocalDatetime(currentMinDate);
let maxUnixTime = getUnixTimeFromLocalDatetime(currentMaxDate);
if (minUnixTime < 0 || maxUnixTime < 0) {
throw new Error('Date is too early');
+2 -5
View File
@@ -7,7 +7,7 @@ import { useUserStore } from '@/stores/user.ts';
import { type NameValue } from '@/core/base.ts';
import { type WeekDayValue } from '@/core/datetime.ts';
import { arrangeArrayWithNewStartIndex } from '@/lib/common.ts';
import { getCurrentYear } from '@/lib/datetime.ts';
import { getAllowedYearRange } from '@/lib/datetime.ts';
export interface TimePickerValue {
value: string;
@@ -34,10 +34,7 @@ export function useDateTimeSelectionBase() {
const isSecondTwoDigits = ref<boolean>(isLongTimeSecondTwoDigits());
const isMeridiemIndicatorFirst = ref<boolean>(isLongTimeMeridiemIndicatorFirst() || false);
const yearRange = ref<number[]>([
2000,
getCurrentYear() + 1
]);
const yearRange = ref<number[]>(getAllowedYearRange());
const meridiemItems = computed<NameValue[]>(() => getAllMeridiemIndicators());
@@ -41,7 +41,7 @@ function getFiscalYearStartFromProps(props: CommonFiscalYearStartSelectionProps)
export function useFiscalYearStartSelectionBase(props: CommonFiscalYearStartSelectionProps) {
const {
getAllMinWeekdayNames,
formatMonthDayToLongDay
formatGregorianCalendarMonthDashDayToLongMonthDay
} = useI18n();
const userStore = useUserStore();
@@ -81,7 +81,7 @@ export function useFiscalYearStartSelectionBase(props: CommonFiscalYearStartSele
fiscalYearStart = FiscalYearStart.Default;
}
return formatMonthDayToLongDay(fiscalYearStart.toMonthDashDayString());
return formatGregorianCalendarMonthDashDayToLongMonthDay(fiscalYearStart.toMonthDashDayString());
});
const allowedMinDate = computed<Date>(() => getLocalDatetimeFromUnixTime(getThisYearFirstUnixTime()));
+7 -11
View File
@@ -1,13 +1,13 @@
import { ref, computed } from 'vue';
import type { Year0BasedMonth } from '@/core/datetime.ts';
import type { TextualYearMonth, Year0BasedMonth } from '@/core/datetime.ts';
import {
getYear0BasedMonthObjectFromUnixTime,
getYear0BasedMonthObjectFromString,
getYearMonthStringFromYear0BasedMonthObject,
getCurrentUnixTime,
getCurrentYear,
getAllowedYearRange,
getThisYearFirstUnixTime,
getYearMonthFirstUnixTime,
getYearMonthLastUnixTime
@@ -21,8 +21,8 @@ export interface MonthSelectionValue {
}
export interface CommonMonthRangeSelectionProps {
minTime?: string;
maxTime?: string;
minTime?: TextualYearMonth;
maxTime?: TextualYearMonth;
title?: string;
hint?: string;
show: boolean;
@@ -64,11 +64,7 @@ export function useMonthRangeSelectionBase(props: CommonMonthRangeSelectionProps
const { formatUnixTimeToLongYearMonth, isLongDateMonthAfterYear } = useI18n();
const { minDate, maxDate } = getMonthRangeFromProps(props);
const yearRange = ref<number[]>([
2000,
getCurrentYear() + 1
]);
const yearRange = ref<number[]>(getAllowedYearRange());
const dateRange = ref<MonthSelectionValue[]>([
minDate,
maxDate
@@ -84,7 +80,7 @@ export function useMonthRangeSelectionBase(props: CommonMonthRangeSelectionProps
month0base: dateRange.value[1].month
})));
function getMonthSelectionValue(yearMonth: string): MonthSelectionValue | null {
function getMonthSelectionValue(yearMonth: TextualYearMonth): MonthSelectionValue | null {
const yearMonthObj = getYear0BasedMonthObjectFromString(yearMonth);
if (!yearMonthObj) {
@@ -97,7 +93,7 @@ export function useMonthRangeSelectionBase(props: CommonMonthRangeSelectionProps
};
}
function getFinalMonthRange(): { minYearMonth: string, maxYearMonth: string } | null {
function getFinalMonthRange(): { minYearMonth: TextualYearMonth | '', maxYearMonth: TextualYearMonth | '' } | null {
if (!dateRange.value[0] || !dateRange.value[1]) {
return null;
}
+12 -24
View File
@@ -4,9 +4,7 @@ import type { Year0BasedMonth } from '@/core/datetime.ts';
import {
getYear0BasedMonthObjectFromUnixTime,
getYear0BasedMonthObjectFromString,
getYearMonthStringFromYear0BasedMonthObject,
getCurrentYear,
getAllowedYearRange,
getThisMonthFirstUnixTime
} from '@/lib/datetime.ts';
@@ -18,7 +16,7 @@ export interface MonthSelectionValue {
}
export interface CommonMonthSelectionProps {
modelValue?: string;
modelValue?: Year0BasedMonth;
title?: string;
hint?: string;
show: boolean;
@@ -28,11 +26,7 @@ function getYearMonthValueFromProps(props: CommonMonthSelectionProps): MonthSele
let value: Year0BasedMonth = getYear0BasedMonthObjectFromUnixTime(getThisMonthFirstUnixTime());
if (props.modelValue) {
const yearMonth = getYear0BasedMonthObjectFromString(props.modelValue);
if (yearMonth) {
value = yearMonth;
}
value = props.modelValue;
}
return {
@@ -44,29 +38,23 @@ function getYearMonthValueFromProps(props: CommonMonthSelectionProps): MonthSele
export function useMonthSelectionBase(props: CommonMonthSelectionProps) {
const { isLongDateMonthAfterYear } = useI18n();
const yearRange = ref<number[]>([
2000,
getCurrentYear() + 1
]);
const yearRange = ref<number[]>(getAllowedYearRange());
const monthValue = ref<MonthSelectionValue>(getYearMonthValueFromProps(props));
const isYearFirst = computed<boolean>(() => isLongDateMonthAfterYear());
function getMonthSelectionValue(yearMonth: string): MonthSelectionValue | null {
const yearMonthObj = getYear0BasedMonthObjectFromString(yearMonth);
if (!yearMonthObj) {
function getMonthSelectionValue(yearMonth: Year0BasedMonth): MonthSelectionValue | null {
if (!yearMonth) {
return null;
}
return {
year: yearMonthObj.year,
month: yearMonthObj.month0base
year: yearMonth.year,
month: yearMonth.month0base
};
}
function getTextualYearMonth(): string | null {
function getYear0BasedMonth(): Year0BasedMonth | null {
if (!monthValue.value) {
return null;
}
@@ -75,10 +63,10 @@ export function useMonthSelectionBase(props: CommonMonthSelectionProps) {
throw new Error('Date is too early');
}
return getYearMonthStringFromYear0BasedMonthObject({
return {
year: monthValue.value.year,
month0base: monthValue.value.month
});
};
}
return {
@@ -89,6 +77,6 @@ export function useMonthSelectionBase(props: CommonMonthSelectionProps) {
isYearFirst,
// functions
getMonthSelectionValue,
getTextualYearMonth
getYear0BasedMonth
};
}
@@ -3,6 +3,7 @@ import { computed } from 'vue';
import { useI18n } from '@/locales/helpers.ts';
import type {
TextualYearMonth,
Year1BasedMonth,
TimeRangeAndDateType,
YearUnixTime,
@@ -18,8 +19,8 @@ import { getAllDateRangesFromItems } from '@/lib/statistics.ts';
export interface CommonMonthlyTrendsChartProps<T extends Year1BasedMonth> {
items: YearMonthItems<T>[];
startYearMonth: string;
endYearMonth: string;
startYearMonth: TextualYearMonth | '';
endYearMonth: TextualYearMonth | '';
fiscalYearStart: number;
sortingType: number;
dateAggregationType: number;
+8 -11
View File
@@ -44,13 +44,13 @@ import { useI18n } from '@/locales/helpers.ts';
import { useUserStore } from '@/stores/user.ts';
import { type WeekDayValue } from '@/core/datetime.ts';
import { type TextualYearMonthDay, type WeekDayValue } from '@/core/datetime.ts';
import { ThemeType } from '@/core/theme.ts';
import { arrangeArrayWithNewStartIndex } from '@/lib/common.ts';
import { getCurrentYear } from '@/lib/datetime.ts';
import { getAllowedYearRange } from '@/lib/datetime.ts';
const props = defineProps<{
modelValue?: string;
modelValue?: TextualYearMonthDay;
disabled?: boolean;
readonly?: boolean;
clearable?: boolean;
@@ -59,22 +59,19 @@ const props = defineProps<{
}>();
const emit = defineEmits<{
(e: 'update:modelValue', value: string): void;
(e: 'update:modelValue', value: TextualYearMonthDay): void;
}>();
const theme = useTheme();
const { tt, getAllMinWeekdayNames, getMonthShortName, formatDateToLongDate, isLongDateMonthAfterYear } = useI18n();
const { tt, getAllMinWeekdayNames, getMonthShortName, formatGregorianCalendarYearDashMonthDashDayToLongDate, isLongDateMonthAfterYear } = useI18n();
const userStore = useUserStore();
const yearRange = ref<number[]>([
2000,
getCurrentYear() + 1
]);
const yearRange = ref<number[]>(getAllowedYearRange());
const dateTime = computed<string>({
get: () => props.modelValue ?? '',
set: (value: string) => emit('update:modelValue', value)
set: (value: string) => emit('update:modelValue', value as TextualYearMonthDay)
});
const isDarkMode = computed<boolean>(() => theme.global.name.value === ThemeType.Dark);
@@ -83,7 +80,7 @@ const dayNames = computed<string[]>(() => arrangeArrayWithNewStartIndex(getAllMi
const isYearFirst = computed<boolean>(() => isLongDateMonthAfterYear());
const displayTime = computed<string>(() => {
if (props.modelValue) {
return formatDateToLongDate(props.modelValue);
return formatGregorianCalendarYearDashMonthDashDayToLongDate(props.modelValue);
} else if (props.noDataText) {
return props.noDataText;
} else {
+3 -3
View File
@@ -105,7 +105,7 @@ import {
getBrowserTimezoneOffsetMinutes,
getLocalDatetimeFromUnixTime,
getActualUnixTimeForStore,
getUnixTime,
getUnixTimeFromLocalDatetime,
getAMOrPM,
getCombinedDateAndTimeValues
} from '@/lib/datetime.ts';
@@ -154,7 +154,7 @@ const dateTime = computed<Date>({
return getLocalDatetimeFromUnixTime(props.modelValue);
},
set: (value: Date) => {
const unixTime = getUnixTime(value);
const unixTime = getUnixTimeFromLocalDatetime(value);
if (unixTime < 0) {
emit('error', 'Date is too early');
@@ -225,7 +225,7 @@ const currentSecond = computed<string>({
});
const isDarkMode = computed<boolean>(() => theme.global.name.value === ThemeType.Dark);
const displayTime = computed<string>(() => formatUnixTimeToLongDateTime(getActualUnixTimeForStore(getUnixTime(dateTime.value), getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes())));
const displayTime = computed<string>(() => formatUnixTimeToLongDateTime(getActualUnixTimeForStore(getUnixTimeFromLocalDatetime(dateTime.value), getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes())));
function toggleMeridiemIndicator(): void {
if (currentMeridiemIndicator.value === MeridiemIndicator.AM.name) {
@@ -71,6 +71,7 @@ import { useI18n } from '@/locales/helpers.ts';
import { type CommonMonthRangeSelectionProps, useMonthRangeSelectionBase } from '@/components/base/MonthRangeSelectionBase.ts';
import { ThemeType } from '@/core/theme.ts';
import { type TextualYearMonth } from '@/core/datetime.ts';
interface DesktopMonthRangeSelectionProps extends CommonMonthRangeSelectionProps {
persistent?: boolean;
@@ -79,7 +80,7 @@ interface DesktopMonthRangeSelectionProps extends CommonMonthRangeSelectionProps
const props = defineProps<DesktopMonthRangeSelectionProps>();
const emit = defineEmits<{
(e: 'update:show', value: boolean): void;
(e: 'dateRange:change', minYearMonth: string, maxYearMonth: string): void;
(e: 'dateRange:change', minYearMonth: TextualYearMonth | '', maxYearMonth: TextualYearMonth | ''): void;
(e: 'error', message: string): void;
}>();
@@ -50,6 +50,7 @@ import { useI18n } from '@/locales/helpers.ts';
import { type CommonMonthSelectionProps, useMonthSelectionBase } from '@/components/base/MonthSelectionBase.ts';
import { ThemeType } from '@/core/theme.ts';
import type { Year0BasedMonth } from '@/core/datetime.ts';
interface DesktopMonthSelectionProps extends CommonMonthSelectionProps {
persistent?: boolean;
@@ -57,7 +58,7 @@ interface DesktopMonthSelectionProps extends CommonMonthSelectionProps {
const props = defineProps<DesktopMonthSelectionProps>();
const emit = defineEmits<{
(e: 'update:modelValue', value: string): void;
(e: 'update:modelValue', value: Year0BasedMonth): void;
(e: 'update:show', value: boolean): void;
(e: 'error', message: string): void;
}>();
@@ -65,7 +66,7 @@ const emit = defineEmits<{
const theme = useTheme();
const { tt, getMonthShortName } = useI18n();
const { yearRange, monthValue, isYearFirst, getMonthSelectionValue, getTextualYearMonth } = useMonthSelectionBase(props);
const { yearRange, monthValue, isYearFirst, getMonthSelectionValue, getYear0BasedMonth } = useMonthSelectionBase(props);
const isDarkMode = computed<boolean>(() => theme.global.name.value === ThemeType.Dark);
const showState = computed<boolean>({
@@ -75,7 +76,7 @@ const showState = computed<boolean>({
function confirm(): void {
try {
const finalMonthRange = getTextualYearMonth();
const finalMonthRange = getYear0BasedMonth();
if (!finalMonthRange) {
return;
+6 -9
View File
@@ -45,17 +45,17 @@ import { useI18n } from '@/locales/helpers.ts';
import { useEnvironmentsStore } from '@/stores/environment.ts';
import { useUserStore } from '@/stores/user.ts';
import { type WeekDayValue } from '@/core/datetime.ts';
import { type TextualYearMonthDay, type WeekDayValue } from '@/core/datetime.ts';
import { arrangeArrayWithNewStartIndex } from '@/lib/common.ts';
import { getCurrentYear } from '@/lib/datetime.ts';
import { getAllowedYearRange } from '@/lib/datetime.ts';
const props = defineProps<{
modelValue?: string;
modelValue?: TextualYearMonthDay;
show: boolean;
}>();
const emit = defineEmits<{
(e: 'update:modelValue', value: string): void;
(e: 'update:modelValue', value: TextualYearMonthDay): void;
(e: 'update:show', value: boolean): void;
}>();
@@ -64,10 +64,7 @@ const { tt, getAllMinWeekdayNames, getMonthShortName, isLongDateMonthAfterYear }
const environmentsStore = useEnvironmentsStore();
const userStore = useUserStore();
const yearRange = ref<number[]>([
2000,
getCurrentYear() + 1
]);
const yearRange = ref<number[]>(getAllowedYearRange());
const dateTime = ref<string>('');
const isDarkMode = computed<boolean>(() => environmentsStore.framework7DarkMode || false);
@@ -81,7 +78,7 @@ function clear(): void {
}
function confirm(): void {
emit('update:modelValue', dateTime.value);
emit('update:modelValue', dateTime.value as TextualYearMonthDay);
emit('update:show', false);
}
@@ -132,7 +132,7 @@ import {
getLocalDatetimeFromUnixTime,
getActualUnixTimeForStore,
getCurrentUnixTime,
getUnixTime,
getUnixTimeFromLocalDatetime,
getAMOrPM,
getCombinedDateAndTimeValues
} from '@/lib/datetime.ts';
@@ -225,7 +225,7 @@ const currentSecond = computed<string>({
});
const isDarkMode = computed<boolean>(() => environmentsStore.framework7DarkMode || false);
const displayTime = computed<string>(() => formatUnixTimeToLongDateTime(getActualUnixTimeForStore(getUnixTime(dateTime.value), getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes())));
const displayTime = computed<string>(() => formatUnixTimeToLongDateTime(getActualUnixTimeForStore(getUnixTimeFromLocalDatetime(dateTime.value), getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes())));
const switchButtonTitle = computed<string>(() => mode.value === 'time' ? 'Date' : 'Time');
function switchMode(): void {
@@ -249,7 +249,7 @@ function confirm(): void {
return;
}
const unixTime = getUnixTime(dateTime.value);
const unixTime = getUnixTimeFromLocalDatetime(dateTime.value);
if (unixTime < 0) {
showToast('Date is too early');
@@ -52,10 +52,12 @@ import { type CommonMonthRangeSelectionProps, useMonthRangeSelectionBase } from
import { useEnvironmentsStore } from '@/stores/environment.ts';
import { type TextualYearMonth } from '@/core/datetime.ts';
const props = defineProps<CommonMonthRangeSelectionProps>();
const emit = defineEmits<{
(e: 'update:show', value: boolean): void;
(e: 'dateRange:change', minYearMonth: string, maxYearMonth: string): void;
(e: 'dateRange:change', minYearMonth: TextualYearMonth | '', maxYearMonth: TextualYearMonth | ''): void;
}>();
const { tt, getMonthShortName } = useI18n();
@@ -44,17 +44,18 @@ import { useI18n } from '@/locales/helpers.ts';
import { useI18nUIComponents } from '@/lib/ui/mobile.ts';
import { type CommonMonthSelectionProps, useMonthSelectionBase } from '@/components/base/MonthSelectionBase.ts';
import type { Year0BasedMonth } from '@/core/datetime.ts';
import { useEnvironmentsStore } from '@/stores/environment.ts';
const props = defineProps<CommonMonthSelectionProps>();
const emit = defineEmits<{
(e: 'update:modelValue', value: string): void;
(e: 'update:modelValue', value: Year0BasedMonth): void;
(e: 'update:show', value: boolean): void;
}>();
const { tt, getMonthShortName } = useI18n();
const { showToast } = useI18nUIComponents();
const { yearRange, monthValue, isYearFirst, getMonthSelectionValue, getTextualYearMonth } = useMonthSelectionBase(props);
const { yearRange, monthValue, isYearFirst, getMonthSelectionValue, getYear0BasedMonth } = useMonthSelectionBase(props);
const environmentsStore = useEnvironmentsStore();
@@ -62,7 +63,7 @@ const isDarkMode = computed<boolean>(() => environmentsStore.framework7DarkMode
function confirm(): void {
try {
const finalMonthRange = getTextualYearMonth();
const finalMonthRange = getYear0BasedMonth();
if (!finalMonthRange) {
return;
+22
View File
@@ -1,5 +1,27 @@
import type { TypeAndName, TypeAndDisplayName } from '@/core/base.ts';
export interface DateTime {
getUnixTime(): number;
getLocalizedCalendarYear(): number;
getGregorianCalendarYear(): number;
getGregorianCalendarQuarter(): number;
getLocalizedCalendarQuarter(): number;
getGregorianCalendarMonth(): number;
getGregorianCalendarMonthName(): string;
getLocalizedCalendarMonth(): number;
getGregorianCalendarDay(): number;
getLocalizedCalendarDay(): number;
getGregorianCalendarYearDashMonthDashDay(): TextualYearMonthDay;
getGregorianCalendarYearDashMonth(): TextualYearMonth;
getWeekDay(): WeekDay;
toGregorianCalendarYearMonthDay(): YearMonthDay;
toGregorianCalendarYear0BasedMonth(): Year0BasedMonth;
format(format: string): string;
}
export type TextualYearMonth = `${number}-${number}`;
export type TextualYearMonthDay = `${number}-${number}-${number}`;
export interface YearQuarter {
readonly year: number;
readonly quarter: number;
+3 -3
View File
@@ -1,4 +1,4 @@
import type { UnixTimeRange } from './datetime.ts';
import type { TextualYearMonth, UnixTimeRange } from './datetime.ts';
export class FiscalYearStart {
public static readonly JanuaryFirstDay = new FiscalYearStart(1, 1);
@@ -75,8 +75,8 @@ export class FiscalYearStart {
return FiscalYearStart.of(month, day);
}
public toMonthDashDayString(): string {
return `${this.month.toString().padStart(2, '0')}-${this.day.toString().padStart(2, '0')}`;
public toMonthDashDayString(): TextualYearMonth {
return `${this.month.toString().padStart(2, '0')}-${this.day.toString().padStart(2, '0')}` as TextualYearMonth;
}
private static isValidFiscalYearMonthDay(month: number, day: number): boolean {
+3 -2
View File
@@ -5,6 +5,7 @@ import { describe, expect, test, beforeAll } from '@jest/globals';
import moment from 'moment-timezone';
// Import all the fiscal year functions from the lib
import type { TextualYearMonth } from '@/core/datetime.ts';
import { FiscalYearStart, FiscalYearUnixTime } from '@/core/fiscalyear.ts';
import {
@@ -230,8 +231,8 @@ describe('getFiscalYearTimeRangeFromUnixTime', () => {
// GET ALL FISCAL YEAR START AND END UNIX TIMES
type TestCase_getAllFiscalYearsStartAndEndUnixTimes = {
startYearMonth: string;
endYearMonth: string;
startYearMonth: TextualYearMonth;
endYearMonth: TextualYearMonth;
fiscalYearStart: string;
fiscalYearStartId: string;
expected: FiscalYearUnixTime[]
+163 -126
View File
@@ -2,11 +2,15 @@ import moment from 'moment-timezone';
import { type unitOfTime } from 'moment/moment';
import {
type DateTime,
type TextualYearMonth,
type TextualYearMonthDay,
type YearUnixTime,
type YearQuarter,
type Year0BasedMonth,
type Year1BasedMonth,
type YearMonthRange,
type YearMonthDay,
type TimeRange,
type TimeRangeAndDateType,
type TimeDifference,
@@ -35,7 +39,120 @@ import {
isNumber
} from './common.ts';
type SupportedDate = Date | moment.Moment;
class MomentDateTime implements DateTime {
private instance: moment.Moment;
private constructor(instance: moment.Moment) {
this.instance = instance;
}
public getUnixTime(): number {
return this.instance.unix();
}
public getLocalizedCalendarYear(): number {
return this.instance.year();
}
public getGregorianCalendarYear(): number {
return this.instance.year();
}
public getGregorianCalendarQuarter(): number {
return this.instance.quarter();
}
public getLocalizedCalendarQuarter(): number {
return this.instance.quarter();
}
public getGregorianCalendarMonth(): number {
return this.instance.month() + 1;
}
public getGregorianCalendarMonthName(): string {
return (Month.valueOf(this.instance.month() + 1) as Month).name;
}
public getLocalizedCalendarMonth(): number {
return this.instance.month() + 1;
}
public getGregorianCalendarDay(): number {
return this.instance.date();
}
public getLocalizedCalendarDay(): number {
return this.instance.date();
}
public getGregorianCalendarYearDashMonthDashDay(): TextualYearMonthDay {
return (this.instance.year() + '-' + (this.instance.month() + 1).toString().padStart(2, '0') + '-' + this.instance.date().toString().padStart(2, '0')) as TextualYearMonthDay;
}
public getGregorianCalendarYearDashMonth(): TextualYearMonth {
return (this.instance.year() + '-' + (this.instance.month() + 1).toString().padStart(2, '0')) as TextualYearMonth;
}
public getWeekDay(): WeekDay {
return WeekDay.valueOf(this.instance.days()) as WeekDay;
}
public toGregorianCalendarYearMonthDay(): YearMonthDay {
return {
year: this.instance.year(),
month: this.instance.month() + 1,
day: this.instance.date()
};
}
public toGregorianCalendarYear0BasedMonth(): Year0BasedMonth {
return {
year: this.instance.year(),
month0base: this.instance.month()
};
}
public format(format: string): string {
return this.instance.format(format);
}
public static of(instance: moment.Moment): DateTime {
return new MomentDateTime(instance);
}
public static now(): DateTime {
return new MomentDateTime(moment());
}
static isYearFirstTime(dateTime: MomentDateTime): boolean {
const currentUnixTime = dateTime.instance.clone().set({ millisecond: 0 }).unix();
const expectedUnxTime = dateTime.instance.clone().set({ millisecond: 0 }).startOf('year').unix();
return currentUnixTime === expectedUnxTime;
}
static isYearLastTime(dateTime: MomentDateTime): boolean {
const currentUnixTime = dateTime.instance.clone().set({ millisecond: 999 }).unix();
const expectedUnxTime = dateTime.instance.clone().set({ millisecond: 999 }).endOf('year').unix();
return currentUnixTime === expectedUnxTime;
}
static isMonthFirstTime(dateTime: MomentDateTime): boolean {
const currentUnixTime = dateTime.instance.clone().set({ millisecond: 0 }).unix();
const expectedUnxTime = dateTime.instance.clone().set({ millisecond: 0 }).startOf('month').unix();
return currentUnixTime === expectedUnxTime;
}
static isMonthLastTime(dateTime: MomentDateTime): boolean {
const currentUnixTime = dateTime.instance.clone().set({ millisecond: 999 }).unix();
const expectedUnxTime = dateTime.instance.clone().set({ millisecond: 999 }).endOf('month').unix();
return currentUnixTime === expectedUnxTime;
}
}
export function getAllowedYearRange(): number[] {
return [2000, moment().year() + 1];
}
export function isYear0BasedMonthValid(year: number, month0base: number): boolean {
if (!isNumber(year) || !isNumber(month0base)) {
@@ -54,7 +171,7 @@ export function getYear0BasedMonthObjectFromUnixTime(unixTime: number): Year0Bas
};
}
export function getYear0BasedMonthObjectFromString(yearMonth: string): Year0BasedMonth | null {
export function getYear0BasedMonthObjectFromString(yearMonth: TextualYearMonth | ''): Year0BasedMonth | null {
if (!isString(yearMonth)) {
return null;
}
@@ -78,12 +195,12 @@ export function getYear0BasedMonthObjectFromString(yearMonth: string): Year0Base
};
}
export function getYearMonthStringFromYear0BasedMonthObject(yearMonth: Year0BasedMonth | null): string {
export function getYearMonthStringFromYear0BasedMonthObject(yearMonth: Year0BasedMonth | null): TextualYearMonth | '' {
if (!yearMonth || !isYear0BasedMonthValid(yearMonth.year, yearMonth.month0base)) {
return '';
}
return `${yearMonth.year}-${yearMonth.month0base + 1}`;
return (`${yearMonth.year}-${yearMonth.month0base + 1}`) as TextualYearMonth;
}
export function getHourIn12HourFormat(hour: number): number {
@@ -122,16 +239,8 @@ export function getUtcOffsetByUtcOffsetMinutes(utcOffsetMinutes: number): string
const offsetHours = Math.trunc(Math.abs(utcOffsetMinutes) / 60);
const offsetMinutes = Math.abs(utcOffsetMinutes) - offsetHours * 60;
let finalOffsetHours = offsetHours.toString();
let finalOffsetMinutes = offsetMinutes.toString();
if (offsetHours < 10) {
finalOffsetHours = '0' + offsetHours;
}
if (offsetMinutes < 10) {
finalOffsetMinutes = '0' + offsetMinutes;
}
const finalOffsetHours = offsetHours.toString().padStart(2, '0');
const finalOffsetMinutes = offsetMinutes.toString().padStart(2, '0');
if (utcOffsetMinutes >= 0) {
return `+${finalOffsetHours}:${finalOffsetMinutes}`;
@@ -180,23 +289,15 @@ export function getDummyUnixTimeForLocalUsage(unixTime: number, utcOffset: numbe
return unixTime + (utcOffset - currentUtcOffset) * 60;
}
export function getCurrentDateTime(): DateTime {
return MomentDateTime.now();
}
export function getCurrentUnixTime(): number {
return moment().unix();
}
export function getCurrentYear(): number {
return moment().year();
}
export function getCurrentYearAndMonth(): string {
return getYearAndMonth(moment());
}
export function getCurrentDay(): number {
return moment().date();
}
export function parseDateFromUnixTime(unixTime: number, utcOffset?: number, currentUtcOffset?: number): moment.Moment {
export function parseDateTimeFromUnixTime(unixTime: number, utcOffset?: number, currentUtcOffset?: number): DateTime {
if (isNumber(utcOffset)) {
if (!isNumber(currentUtcOffset)) {
currentUtcOffset = getTimezoneOffsetMinutes();
@@ -205,73 +306,31 @@ export function parseDateFromUnixTime(unixTime: number, utcOffset?: number, curr
unixTime = getDummyUnixTimeForLocalUsage(unixTime, utcOffset, currentUtcOffset);
}
return moment.unix(unixTime);
return MomentDateTime.of(moment.unix(unixTime));
}
export function formatUnixTime(unixTime: number, format: string, utcOffset?: number, currentUtcOffset?: number) {
return parseDateFromUnixTime(unixTime, utcOffset, currentUtcOffset).format(format);
export function formatUnixTime(unixTime: number, format: string, utcOffset?: number, currentUtcOffset?: number): string {
return parseDateTimeFromUnixTime(unixTime, utcOffset, currentUtcOffset).format(format);
}
export function formatCurrentTime(format: string): string {
return moment().format(format);
}
export function formatDate(date: string, format: string): string {
export function formatGregorianCalendarYearDashMonthDashDay(date: TextualYearMonthDay, format: string): string {
return moment(date, 'YYYY-MM-DD').format(format);
}
export function formatMonthDay(monthDay: string, format: string): string {
export function formatGregorianCalendarMonthDashDay(monthDay: TextualYearMonth, format: string): string {
return moment(monthDay, 'MM-DD').format(format);
}
export function getUnixTime(date: SupportedDate): number {
return moment(date).unix();
}
export function getShortDate(date: SupportedDate): string {
date = moment(date);
return date.year() + '-' + (date.month() + 1) + '-' + date.date();
}
export function getYear(date: SupportedDate): number {
return moment(date).year();
}
export function getQuarter(date: SupportedDate): number {
return moment(date).quarter();
}
export function getMonth(date: SupportedDate): number {
return moment(date).month() + 1;
}
export function getYearAndMonth(date: SupportedDate): string {
const year = getYear(date);
const month = getMonth(date);
return `${year}-${month}`;
}
export function getYearAndMonthFromUnixTime(unixTime: number): string {
export function getGregorianCalendarYearAndMonthFromUnixTime(unixTime: number): TextualYearMonth | '' {
if (!unixTime) {
return '';
}
return getYearAndMonth(parseDateFromUnixTime(unixTime));
}
export function getDay(date: SupportedDate): number {
return moment(date).date();
}
export function getDayOfWeekName(date: SupportedDate): string {
const dayOfWeek = moment(date).days();
return (WeekDay.valueOf(dayOfWeek) as WeekDay).name;
}
export function getMonthName(date: SupportedDate): string {
const month = moment(date).month();
return (Month.valueOf(month + 1) as Month).name;
return parseDateTimeFromUnixTime(unixTime).getGregorianCalendarYearDashMonth();
}
export function getAMOrPM(hour: number): string {
@@ -296,15 +355,6 @@ export function getTimeDifferenceHoursAndMinutes(timeDifferenceInMinutes: number
};
}
export function getMinuteFirstUnixTime(date: SupportedDate): number {
const datetime = moment(date);
return datetime.set({ second: 0, millisecond: 0 }).unix();
}
export function getMinuteLastUnixTime(date: SupportedDate): number {
return moment.unix(getMinuteFirstUnixTime(date)).add(1, 'minutes').subtract(1, 'seconds').unix();
}
export function getTodayFirstUnixTime(): number {
return moment().set({ hour: 0, minute: 0, second: 0, millisecond: 0 }).unix();
}
@@ -412,7 +462,7 @@ export function getQuarterLastUnixTime(yearQuarter: YearQuarter): number {
return moment.unix(getQuarterFirstUnixTime(yearQuarter)).add(3, 'months').subtract(1, 'seconds').unix();
}
export function getYearMonthFirstUnixTime(yearMonth: Year0BasedMonth | Year1BasedMonth | string): number {
export function getYearMonthFirstUnixTime(yearMonth: Year0BasedMonth | Year1BasedMonth | TextualYearMonth | ''): number {
let yearMonthObj: Year0BasedMonth | null = null;
if (isString(yearMonth)) {
@@ -433,11 +483,11 @@ export function getYearMonthFirstUnixTime(yearMonth: Year0BasedMonth | Year1Base
return moment().set({ year: yearMonthObj.year, month: yearMonthObj.month0base, date: 1, hour: 0, minute: 0, second: 0, millisecond: 0 }).unix();
}
export function getYearMonthLastUnixTime(yearMonth: Year0BasedMonth | Year1BasedMonth | string): number {
export function getYearMonthLastUnixTime(yearMonth: Year0BasedMonth | Year1BasedMonth | TextualYearMonth | ''): number {
return moment.unix(getYearMonthFirstUnixTime(yearMonth)).add(1, 'months').subtract(1, 'seconds').unix();
}
export function getStartEndYearMonthRange(startYearMonth: Year0BasedMonth | Year1BasedMonth | string, endYearMonth: Year0BasedMonth | Year1BasedMonth | string): YearMonthRange | null {
export function getStartEndYearMonthRange(startYearMonth: Year0BasedMonth | Year1BasedMonth | TextualYearMonth | '', endYearMonth: Year0BasedMonth | Year1BasedMonth | TextualYearMonth | ''): YearMonthRange | null {
let startYearMonthObj: Year0BasedMonth | null = null;
let endYearMonthObj: Year0BasedMonth | null = null;
@@ -473,7 +523,7 @@ export function getStartEndYearMonthRange(startYearMonth: Year0BasedMonth | Year
};
}
export function getAllYearsStartAndEndUnixTimes(startYearMonth: Year0BasedMonth | Year1BasedMonth | string, endYearMonth: Year0BasedMonth | Year1BasedMonth | string): YearUnixTime[] {
export function getAllYearsStartAndEndUnixTimes(startYearMonth: Year0BasedMonth | Year1BasedMonth | TextualYearMonth | '', endYearMonth: Year0BasedMonth | Year1BasedMonth | TextualYearMonth | ''): YearUnixTime[] {
const allYearTimes: YearUnixTime[] = [];
const range = getStartEndYearMonthRange(startYearMonth, endYearMonth);
@@ -494,7 +544,7 @@ export function getAllYearsStartAndEndUnixTimes(startYearMonth: Year0BasedMonth
return allYearTimes;
}
export function getAllFiscalYearsStartAndEndUnixTimes(startYearMonth: Year0BasedMonth | Year1BasedMonth | string, endYearMonth: Year0BasedMonth | Year1BasedMonth | string, fiscalYearStartValue: number): FiscalYearUnixTime[] {
export function getAllFiscalYearsStartAndEndUnixTimes(startYearMonth: Year0BasedMonth | Year1BasedMonth | TextualYearMonth | '', endYearMonth: Year0BasedMonth | Year1BasedMonth | TextualYearMonth | '', fiscalYearStartValue: number): FiscalYearUnixTime[] {
// user selects date range: start=2024-01 and end=2026-12
// result should be 4x FiscalYearUnixTime made up of:
// - 2024-01->2024-06 (FY 24) - input start year-month->end of fiscal year in which the input start year-month falls
@@ -544,7 +594,7 @@ export function getAllFiscalYearsStartAndEndUnixTimes(startYearMonth: Year0Based
return allFiscalYearTimes;
}
export function getAllQuartersStartAndEndUnixTimes(startYearMonth: Year0BasedMonth | Year1BasedMonth | string, endYearMonth: Year0BasedMonth | Year1BasedMonth | string): YearQuarterUnixTime[] {
export function getAllQuartersStartAndEndUnixTimes(startYearMonth: Year0BasedMonth | Year1BasedMonth | TextualYearMonth | '', endYearMonth: Year0BasedMonth | Year1BasedMonth | TextualYearMonth | ''): YearQuarterUnixTime[] {
const allYearQuarterTimes: YearQuarterUnixTime[] = [];
const range = getStartEndYearMonthRange(startYearMonth, endYearMonth);
@@ -578,7 +628,7 @@ export function getAllQuartersStartAndEndUnixTimes(startYearMonth: Year0BasedMon
return allYearQuarterTimes;
}
export function getAllMonthsStartAndEndUnixTimes(startYearMonth: Year0BasedMonth | Year1BasedMonth | string, endYearMonth: Year0BasedMonth | Year1BasedMonth | string): YearMonthUnixTime[] {
export function getAllMonthsStartAndEndUnixTimes(startYearMonth: Year0BasedMonth | Year1BasedMonth | TextualYearMonth | '', endYearMonth: Year0BasedMonth | Year1BasedMonth | TextualYearMonth | ''): YearMonthUnixTime[] {
const allYearMonthTimes: YearMonthUnixTime[] = [];
const range = getStartEndYearMonthRange(startYearMonth, endYearMonth);
@@ -622,16 +672,11 @@ export function getAllDaysStartAndEndUnixTimes(startUnixTime: number, endUnixTim
let unixTime: number = startUnixTime;
while (unixTime <= endUnixTime) {
const currentDay = parseDateFromUnixTime(unixTime);
const currentDateTime = parseDateTimeFromUnixTime(unixTime);
const currentDayMinUnixTime = getDayFirstUnixTimeBySpecifiedUnixTime(unixTime);
const currentDayMaxUnixTime = getDayLastUnixTimeBySpecifiedUnixTime(unixTime);
allYearMonthDayTimes.push(YearMonthDayUnixTime.of({
year: currentDay.year(),
month: currentDay.month() + 1,
day: currentDay.date()
}, currentDayMinUnixTime, currentDayMaxUnixTime));
allYearMonthDayTimes.push(YearMonthDayUnixTime.of(currentDateTime.toGregorianCalendarYearMonthDay(), currentDayMinUnixTime, currentDayMaxUnixTime));
unixTime = currentDayMaxUnixTime + 1;
}
@@ -649,15 +694,15 @@ export function getDateTimeFormatType<T extends DateFormat | TimeFormat>(allForm
}
export function getShiftedDateRange(minTime: number, maxTime: number, scale: number): TimeRange {
const minDateTime = parseDateFromUnixTime(minTime).set({ millisecond: 0 });
const maxDateTime = parseDateFromUnixTime(maxTime).set({ millisecond: 999 });
const minDateTime = moment.unix(parseDateTimeFromUnixTime(minTime).getUnixTime()).set({ millisecond: 0 });
const maxDateTime = moment.unix(parseDateTimeFromUnixTime(maxTime).getUnixTime()).set({ millisecond: 999 });
const firstDayOfMonth = minDateTime.clone().startOf('month');
const lastDayOfMonth = maxDateTime.clone().endOf('month');
// check whether the date range matches full months
if (firstDayOfMonth.unix() === minDateTime.unix() && lastDayOfMonth.unix() === maxDateTime.unix()) {
const months = getYear(maxDateTime) * 12 + getMonth(maxDateTime) - getYear(minDateTime) * 12 - getMonth(minDateTime) + 1;
const months = maxDateTime.year() * 12 + (maxDateTime.month() + 1) - minDateTime.year() * 12 - (minDateTime.month() + 1) + 1;
const newMinDateTime = minDateTime.add(months * scale, 'months');
const newMaxDateTime = newMinDateTime.clone().add(months, 'months').subtract(1, 'seconds');
@@ -848,7 +893,7 @@ export function getDateRangeByBillingCycleDateType(dateType: number, firstDayOfW
if (dateType === DateRange.PreviousBillingCycle.type || dateType === DateRange.CurrentBillingCycle.type) { // Previous Billing Cycle | Current Billing Cycle
if (statementDate) {
if (getCurrentDay() <= statementDate) {
if (getCurrentDateTime().getGregorianCalendarDay() <= statementDate) {
maxTime = getThisMonthSpecifiedDayLastUnixTime(statementDate);
minTime = getUnixTimeBeforeUnixTime(getUnixTimeAfterUnixTime(getThisMonthSpecifiedDayFirstUnixTime(statementDate), 1, 'days'), 1, 'months');
} else {
@@ -898,8 +943,8 @@ export function getRecentMonthDateRanges(monthCount: number): RecentMonthDateRan
const maxTime = getUnixTimeBeforeUnixTime(getUnixTimeAfterUnixTime(minTime, 1, 'months'), 1, 'seconds');
let dateType = DateRange.Custom.type;
const year = getYear(parseDateFromUnixTime(minTime));
const month = getMonth(parseDateFromUnixTime(minTime));
const year = parseDateTimeFromUnixTime(minTime).getGregorianCalendarYear();
const month = parseDateTimeFromUnixTime(minTime).getGregorianCalendarMonth();
if (i === 0) {
dateType = DateRange.ThisMonth.type;
@@ -1004,7 +1049,7 @@ export function getCombinedDateAndTimeValues(date: Date, hour: string, minute: s
return newDateTime;
}
export function getValidMonthDayOrCurrentDayShortDate(unixTime: number, currentShortDate: string): string {
export function getValidMonthDayOrCurrentDayShortDate(unixTime: number, currentShortDate: string): TextualYearMonthDay {
const currentTime = moment();
const monthLastTime = moment.unix(getMonthLastUnixTimeBySpecifiedUnixTime(unixTime));
@@ -1015,43 +1060,35 @@ export function getValidMonthDayOrCurrentDayShortDate(unixTime: number, currentS
const currentDay = parseInt(yearMonthDay[2]);
if (currentDay < monthLastTime.date()) {
return getShortDate(monthLastTime.set({ date: currentDay }));
return MomentDateTime.of(monthLastTime.set({ date: currentDay })).getGregorianCalendarYearDashMonthDashDay();
}
}
}
if (monthLastTime.year() === currentTime.year() && monthLastTime.month() === currentTime.month()) {
return getShortDate(currentTime);
return MomentDateTime.of(currentTime).getGregorianCalendarYearDashMonthDashDay();
}
return getShortDate(monthLastTime);
return MomentDateTime.of(monthLastTime).getGregorianCalendarYearDashMonthDashDay();
}
export function isDateRangeMatchFullYears(minTime: number, maxTime: number): boolean {
const minDateTime = parseDateFromUnixTime(minTime).set({ millisecond: 0 });
const maxDateTime = parseDateFromUnixTime(maxTime).set({ millisecond: 999 });
const firstDayOfYear = minDateTime.clone().startOf('year');
const lastDayOfYear = maxDateTime.clone().endOf('year');
return firstDayOfYear.unix() === minDateTime.unix() && lastDayOfYear.unix() === maxDateTime.unix();
const minDateTime = parseDateTimeFromUnixTime(minTime);
const maxDateTime = parseDateTimeFromUnixTime(maxTime);
return MomentDateTime.isYearFirstTime(minDateTime as MomentDateTime) && MomentDateTime.isYearLastTime(maxDateTime as MomentDateTime);
}
export function isDateRangeMatchFullMonths(minTime: number, maxTime: number): boolean {
const minDateTime = parseDateFromUnixTime(minTime).set({ millisecond: 0 });
const maxDateTime = parseDateFromUnixTime(maxTime).set({ millisecond: 999 });
const firstDayOfMonth = minDateTime.clone().startOf('month');
const lastDayOfMonth = maxDateTime.clone().endOf('month');
return firstDayOfMonth.unix() === minDateTime.unix() && lastDayOfMonth.unix() === maxDateTime.unix();
const minDateTime = parseDateTimeFromUnixTime(minTime);
const maxDateTime = parseDateTimeFromUnixTime(maxTime);
return MomentDateTime.isMonthFirstTime(minDateTime as MomentDateTime) && MomentDateTime.isMonthLastTime(maxDateTime as MomentDateTime);
}
export function isDateRangeMatchOneMonth(minTime: number, maxTime: number): boolean {
const minDateTime = parseDateFromUnixTime(minTime);
const maxDateTime = parseDateFromUnixTime(maxTime);
const minDateTime = parseDateTimeFromUnixTime(minTime);
const maxDateTime = parseDateTimeFromUnixTime(maxTime);
if (getYear(minDateTime) !== getYear(maxDateTime) || getMonth(minDateTime) !== getMonth(maxDateTime)) {
if (minDateTime.getGregorianCalendarYear() !== maxDateTime.getGregorianCalendarYear() || minDateTime.getGregorianCalendarMonth() !== maxDateTime.getGregorianCalendarMonth()) {
return false;
}
+5 -5
View File
@@ -1,4 +1,4 @@
import type { Year1BasedMonth, YearUnixTime, YearQuarterUnixTime, YearMonthUnixTime } from '@/core/datetime.ts';
import type { TextualYearMonth, Year1BasedMonth, YearUnixTime, YearQuarterUnixTime, YearMonthUnixTime } from '@/core/datetime.ts';
import type { FiscalYearUnixTime } from '@/core/fiscalyear.ts';
import { ChartSortingType, ChartDateAggregationType } from '@/core/statistics.ts';
import type {
@@ -48,7 +48,7 @@ export function sortStatisticsItems<T extends SortableTransactionStatisticDataIt
}
}
export function getAllDateRangesFromItems<T extends Year1BasedMonth>(items: YearMonthItems<T>[], startYearMonth: Year1BasedMonth | string, endYearMonth: Year1BasedMonth | string, fiscalYearStart: number, dateAggregationType: number): YearUnixTime[] | FiscalYearUnixTime[] | YearQuarterUnixTime[] | YearMonthUnixTime[] {
export function getAllDateRangesFromItems<T extends Year1BasedMonth>(items: YearMonthItems<T>[], startYearMonth: Year1BasedMonth | TextualYearMonth | '', endYearMonth: Year1BasedMonth | TextualYearMonth | '', fiscalYearStart: number, dateAggregationType: number): YearUnixTime[] | FiscalYearUnixTime[] | YearQuarterUnixTime[] | YearMonthUnixTime[] {
if ((!startYearMonth || !endYearMonth) && items && items.length) {
let minYear = Number.MAX_SAFE_INTEGER, minMonth = Number.MAX_SAFE_INTEGER, maxYear = 0, maxMonth = 0;
@@ -70,14 +70,14 @@ export function getAllDateRangesFromItems<T extends Year1BasedMonth>(items: Year
}
}
startYearMonth = `${minYear}-${minMonth}`;
endYearMonth = `${maxYear}-${maxMonth}`;
startYearMonth = `${minYear}-${minMonth}` as TextualYearMonth;
endYearMonth = `${maxYear}-${maxMonth}` as TextualYearMonth;
}
return getAllDateRangesByYearMonthRange(startYearMonth, endYearMonth, fiscalYearStart, dateAggregationType);
}
export function getAllDateRangesByYearMonthRange(startYearMonth: Year1BasedMonth | string, endYearMonth: Year1BasedMonth | string, fiscalYearStart: number, dateAggregationType: number): YearUnixTime[] | FiscalYearUnixTime[] | YearQuarterUnixTime[] | YearMonthUnixTime[] {
export function getAllDateRangesByYearMonthRange(startYearMonth: Year1BasedMonth | TextualYearMonth | '', endYearMonth: Year1BasedMonth | TextualYearMonth | '', fiscalYearStart: number, dateAggregationType: number): YearUnixTime[] | FiscalYearUnixTime[] | YearQuarterUnixTime[] | YearMonthUnixTime[] {
if (!startYearMonth || !endYearMonth) {
return [];
}
+22 -22
View File
@@ -16,6 +16,8 @@ import {
} from '@/core/text.ts';
import {
type TextualYearMonth,
type TextualYearMonthDay,
type DateFormat,
type TimeFormat,
type LocalizedDateTimeFormat,
@@ -148,12 +150,13 @@ import {
import {
formatCurrentTime,
formatDate,
formatMonthDay,
formatGregorianCalendarYearDashMonthDashDay,
formatGregorianCalendarMonthDashDay,
formatUnixTime,
getBrowserTimezoneOffset,
getBrowserTimezoneOffsetMinutes,
getCurrentUnixTime,
parseDateTimeFromUnixTime,
getDateTimeFormatType,
getFiscalYearTimeRangeFromUnixTime,
getFiscalYearTimeRangeFromYear,
@@ -161,12 +164,9 @@ import {
getTimeDifferenceHoursAndMinutes,
getTimezoneOffset,
getTimezoneOffsetMinutes,
getYear,
getQuarter,
isDateRangeMatchFullMonths,
isDateRangeMatchFullYears,
isPM,
parseDateFromUnixTime,
isPM
} from '@/lib/datetime.ts';
import {
@@ -1441,12 +1441,12 @@ export function useI18n() {
});
}
function getWeekdayShortName(weekDayName: string): string {
return t(`datetime.${weekDayName}.short`);
function getWeekdayShortName(weekDay: WeekDay): string {
return t(`datetime.${weekDay.name}.short`);
}
function getWeekdayLongName(weekDayName: string): string {
return t(`datetime.${weekDayName}.long`);
function getWeekdayLongName(weekDay: WeekDay): string {
return t(`datetime.${weekDay.name}.long`);
}
function getMultiMonthdayShortNames(monthDays: number[]): string {
@@ -1618,18 +1618,18 @@ export function useI18n() {
return getLocalizedLongTimeFormat().indexOf('ss') >= 0;
}
function formatDateToLongDate(date: string): string {
return formatDate(date, getLocalizedLongDateFormat());
function formatGregorianCalendarYearDashMonthDashDayToLongDate(date: TextualYearMonthDay): string {
return formatGregorianCalendarYearDashMonthDashDay(date, getLocalizedLongDateFormat());
}
function formatMonthDayToLongDay(monthDay: string): string {
return formatMonthDay(monthDay, getLocalizedLongMonthDayFormat());
function formatGregorianCalendarMonthDashDayToLongMonthDay(monthDay: TextualYearMonth): string {
return formatGregorianCalendarMonthDashDay(monthDay, getLocalizedLongMonthDayFormat());
}
function formatUnixTimeToYearQuarter(unixTime: number): string {
const date = parseDateFromUnixTime(unixTime);
const year = getYear(date);
const quarter = getQuarter(date);
const date = parseDateTimeFromUnixTime(unixTime);
const year = date.getLocalizedCalendarYear();
const quarter = date.getLocalizedCalendarQuarter();
return formatYearQuarter(year, quarter);
}
@@ -1675,8 +1675,8 @@ export function useI18n() {
return displayStartTime !== displayEndTime ? `${displayStartTime} ~ ${displayEndTime}` : displayStartTime;
}
const startTimeYear = getYear(parseDateFromUnixTime(startTime));
const endTimeYear = getYear(parseDateFromUnixTime(endTime));
const startTimeYear = parseDateTimeFromUnixTime(startTime).getLocalizedCalendarYear();
const endTimeYear = parseDateTimeFromUnixTime(endTime).getLocalizedCalendarYear();
const format = getLocalizedShortDateFormat();
const displayStartTime = formatUnixTime(startTime, format);
@@ -1734,7 +1734,7 @@ export function useI18n() {
fiscalYearStart = FiscalYearStart.Default;
}
return formatMonthDayToLongDay(fiscalYearStart.toMonthDashDayString());
return formatGregorianCalendarMonthDashDayToLongMonthDay(fiscalYearStart.toMonthDashDayString());
}
function getTimezoneDifferenceDisplayText(utcOffset: number): string {
@@ -2168,8 +2168,8 @@ export function useI18n() {
formatUnixTimeToShortMonthDay: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedShortMonthDayFormat(), utcOffset, currentUtcOffset),
formatUnixTimeToLongTime: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedLongTimeFormat(), utcOffset, currentUtcOffset),
formatUnixTimeToShortTime: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedShortTimeFormat(), utcOffset, currentUtcOffset),
formatDateToLongDate,
formatMonthDayToLongDay,
formatGregorianCalendarYearDashMonthDashDayToLongDate,
formatGregorianCalendarMonthDashDayToLongMonthDay,
formatUnixTimeToYearQuarter,
formatYearQuarter,
formatDateRange,
+14 -14
View File
@@ -1,5 +1,5 @@
import type { PartialRecord } from '@/core/base.ts';
import type { Year1BasedMonth, StartEndTime } from '@/core/datetime.ts';
import type { Year1BasedMonth, TextualYearMonthDay, StartEndTime, WeekDay } from '@/core/datetime.ts';
import { type Coordinate, getNormalizedCoordinate } from '@/core/coordinate.ts';
import { TransactionType } from '@/core/transaction.ts';
@@ -35,9 +35,9 @@ export class Transaction implements TransactionInfoResponse {
private _destinationAccount?: Account; // only for displaying transaction
private _tags?: TransactionTag[]; // only for displaying transaction
private _date?: string = undefined; // only for displaying transaction in transaction list
private _day?: number = undefined; // only for displaying transaction in transaction list
private _dayOfWeek?: string = undefined; // only for displaying transaction in transaction list
private _gregorianCalendarYearDashMonthDashDay?: TextualYearMonthDay = undefined; // only for displaying transaction in transaction list
private _gregorianCalendarDayOfMonth?: number = undefined; // only for displaying transaction in transaction list
private _displayDayOfWeek?: WeekDay = undefined; // only for displaying transaction in transaction list
protected constructor(id: string, timeSequenceId: string, type: number, categoryId: string, time: number, timeZone: string | undefined, utcOffset: number, sourceAccountId: string, destinationAccountId: string, sourceAmount: number, destinationAmount: number, hideAmount: boolean, tagIds: string[], comment: string, editable: boolean) {
this.id = id;
@@ -106,16 +106,16 @@ export class Transaction implements TransactionInfoResponse {
return ret;
}
public get date(): string | undefined {
return this._date;
public get gregorianCalendarYearDashMonthDashDay(): TextualYearMonthDay | undefined {
return this._gregorianCalendarYearDashMonthDashDay;
}
public get day(): number | undefined {
return this._day;
public get gregorianCalendarDayOfMonth(): number | undefined {
return this._gregorianCalendarDayOfMonth;
}
public get dayOfWeek(): string | undefined {
return this._dayOfWeek;
public get displayDayOfWeek(): WeekDay | undefined {
return this._displayDayOfWeek;
}
public getCategoryId(): string {
@@ -220,10 +220,10 @@ export class Transaction implements TransactionInfoResponse {
this._geoLocation = undefined;
}
public setDisplayDate(date: string, day: number, dayOfWeek: string): void {
this._date = date;
this._day = day;
this._dayOfWeek = dayOfWeek;
public setDisplayDate(gregorianCalendarYearDashMonthDashDay: TextualYearMonthDay, gregorianCalendarDayOfMonth: number, displayDayOfWeek: WeekDay): void {
this._gregorianCalendarYearDashMonthDashDay = gregorianCalendarYearDashMonthDashDay;
this._gregorianCalendarDayOfMonth = gregorianCalendarDayOfMonth;
this._displayDayOfWeek = displayDayOfWeek;
}
public toCreateRequest(clientSessionId: string, actualTime?: number): TransactionCreateRequest {
+6 -5
View File
@@ -1,3 +1,4 @@
import { type TextualYearMonthDay } from '@/core/datetime.ts';
import { TransactionType } from '@/core/transaction.ts';
import { TemplateType } from '@/core/template.ts';
@@ -8,13 +9,13 @@ export class TransactionTemplate extends Transaction implements TransactionTempl
public name: string;
public scheduledFrequencyType?: number;
public scheduledFrequency?: string;
public scheduledStartDate?: string;
public scheduledEndDate?: string;
public scheduledStartDate?: TextualYearMonthDay;
public scheduledEndDate?: TextualYearMonthDay;
public scheduledAt?: number;
public displayOrder: number;
public hidden: boolean;
private constructor(id: string, templateType: number, name: string, type: number, categoryId: string, timeZone: string | undefined, utcOffset: number, sourceAccountId: string, destinationAccountId: string, sourceAmount: number, destinationAmount: number, hideAmount: boolean, scheduledFrequencyType: number | undefined, scheduledFrequency: string | undefined, scheduledStartDate: string | undefined, scheduledEndDate: string | undefined, scheduledAt: number | undefined, tagIds: string[], comment: string, editable: boolean, displayOrder: number, hidden: boolean) {
private constructor(id: string, templateType: number, name: string, type: number, categoryId: string, timeZone: string | undefined, utcOffset: number, sourceAccountId: string, destinationAccountId: string, sourceAmount: number, destinationAmount: number, hideAmount: boolean, scheduledFrequencyType: number | undefined, scheduledFrequency: string | undefined, scheduledStartDate: TextualYearMonthDay | undefined, scheduledEndDate: TextualYearMonthDay | undefined, scheduledAt: number | undefined, tagIds: string[], comment: string, editable: boolean, displayOrder: number, hidden: boolean) {
super(id, '', type, categoryId, 0, timeZone, utcOffset, sourceAccountId, destinationAccountId, sourceAmount, destinationAmount, hideAmount, tagIds, comment, editable);
this.templateType = templateType;
this.name = name;
@@ -211,8 +212,8 @@ export interface TransactionTemplateInfoResponse extends TransactionInfoResponse
readonly name: string;
readonly scheduledFrequencyType?: number;
readonly scheduledFrequency?: string;
readonly scheduledStartDate?: string;
readonly scheduledEndDate?: string;
readonly scheduledStartDate?: TextualYearMonthDay;
readonly scheduledEndDate?: TextualYearMonthDay;
readonly scheduledAt?: number;
readonly displayOrder: number;
readonly hidden: boolean;
+8 -8
View File
@@ -7,7 +7,7 @@ import { useAccountsStore } from './account.ts';
import { useTransactionCategoriesStore } from './transactionCategory.ts';
import { useExchangeRatesStore } from './exchangeRates.ts';
import { type TimeRangeAndDateType, DateRangeScene, DateRange } from '@/core/datetime.ts';
import { type TextualYearMonth, type TimeRangeAndDateType, DateRangeScene, DateRange } from '@/core/datetime.ts';
import { TimezoneTypeForStatistics } from '@/core/timezone.ts';
import { CategoryType } from '@/core/category.ts';
import { TransactionTagFilterType } from '@/core/transaction.ts';
@@ -50,7 +50,7 @@ import {
isObjectEmpty,
objectFieldToArrayItem
} from '@/lib/common.ts';
import { getYearAndMonthFromUnixTime, getDateRangeByDateType } from '@/lib/datetime.ts';
import { getGregorianCalendarYearAndMonthFromUnixTime, getDateRangeByDateType } from '@/lib/datetime.ts';
import { getFinalAccountIdsByFilteredAccountIds } from '@/lib/account.ts';
import { getFinalCategoryIdsByFilteredCategoryIds } from '@/lib/category.ts';
import { sortStatisticsItems } from '@/lib/statistics.ts';
@@ -118,8 +118,8 @@ export interface TransactionStatisticsPartialFilter {
categoricalChartEndTime?: number;
trendChartType?: number;
trendChartDateType?: number;
trendChartStartYearMonth?: string;
trendChartEndYearMonth?: string;
trendChartStartYearMonth?: TextualYearMonth | '';
trendChartEndYearMonth?: TextualYearMonth | '';
filterAccountIds?: Record<string, boolean>;
filterCategoryIds?: Record<string, boolean>;
tagIds?: string;
@@ -136,8 +136,8 @@ export interface TransactionStatisticsFilter extends TransactionStatisticsPartia
categoricalChartEndTime: number;
trendChartType: number;
trendChartDateType: number;
trendChartStartYearMonth: string;
trendChartEndYearMonth: string;
trendChartStartYearMonth: TextualYearMonth | '';
trendChartEndYearMonth: TextualYearMonth | '';
filterAccountIds: Record<string, boolean>;
filterCategoryIds: Record<string, boolean>;
tagIds: string;
@@ -800,8 +800,8 @@ export const useStatisticsStore = defineStore('statistics', () => {
if (trendChartDateRange) {
transactionStatisticsFilter.value.trendChartDateType = trendChartDateRange.dateType;
transactionStatisticsFilter.value.trendChartStartYearMonth = getYearAndMonthFromUnixTime(trendChartDateRange.minTime);
transactionStatisticsFilter.value.trendChartEndYearMonth = getYearAndMonthFromUnixTime(trendChartDateRange.maxTime);
transactionStatisticsFilter.value.trendChartStartYearMonth = getGregorianCalendarYearAndMonthFromUnixTime(trendChartDateRange.minTime);
transactionStatisticsFilter.value.trendChartEndYearMonth = getGregorianCalendarYearAndMonthFromUnixTime(trendChartDateRange.maxTime);
}
}
+15 -21
View File
@@ -10,7 +10,7 @@ import { useStatisticsStore } from './statistics.ts';
import { useExchangeRatesStore } from './exchangeRates.ts';
import type { BeforeResolveFunction } from '@/core/base.ts';
import { DateRange } from '@/core/datetime.ts';
import { type TextualYearMonth, DateRange } from '@/core/datetime.ts';
import { CategoryType } from '@/core/category.ts';
import { TransactionType, TransactionTagFilterType } from '@/core/transaction.ts';
import { TRANSACTION_MIN_AMOUNT, TRANSACTION_MAX_AMOUNT } from '@/consts/transaction.ts';
@@ -51,13 +51,7 @@ import {
getTimezoneOffsetMinutes,
getBrowserTimezoneOffsetMinutes,
getActualUnixTimeForStore,
parseDateFromUnixTime,
getShortDate,
getYear,
getMonth,
getYearAndMonth,
getDay,
getDayOfWeekName
parseDateTimeFromUnixTime
} from '@/lib/datetime.ts';
import { getAmountWithDecimalNumberCount } from '@/lib/numeral.ts';
import { getCurrencyFraction } from '@/lib/currency.ts';
@@ -101,7 +95,7 @@ export interface TransactionTotalAmount {
export interface TransactionMonthList {
readonly year: number;
readonly month: number; // 1-based (1 = January, 12 = December)
readonly yearMonth: string;
readonly yearDashMonth: TextualYearMonth;
opened: boolean;
readonly items: Transaction[];
readonly totalAmount: TransactionTotalAmount;
@@ -177,10 +171,10 @@ export const useTransactionsStore = defineStore('transactions', () => {
const item = transactionPageWrapper.items[i];
fillTransactionObject(item, currentUtcOffset);
const transactionTime = parseDateFromUnixTime(item.time, item.utcOffset, currentUtcOffset);
const transactionYear = getYear(transactionTime);
const transactionMonth = getMonth(transactionTime);
const transactionYearMonth = getYearAndMonth(transactionTime);
const transactionTime = parseDateTimeFromUnixTime(item.time, item.utcOffset, currentUtcOffset);
const transactionYear = transactionTime.getGregorianCalendarYear();
const transactionMonth = transactionTime.getGregorianCalendarMonth();
const transactionYearDashMonth = transactionTime.getGregorianCalendarYearDashMonth();
if (i === 0 && transactions.value.length > 0) {
const lastMonthList = transactions.value[transactions.value.length - 1];
@@ -216,7 +210,7 @@ export const useTransactionsStore = defineStore('transactions', () => {
const monthList: TransactionMonthList = {
year: transactionYear,
month: transactionMonth,
yearMonth: transactionYearMonth,
yearDashMonth: transactionYearDashMonth,
opened: autoExpand,
items: [],
totalAmount: {
@@ -250,9 +244,9 @@ export const useTransactionsStore = defineStore('transactions', () => {
function updateTransactionInTransactionList({ transaction, defaultCurrency }: { transaction: Transaction, defaultCurrency: string }): void {
const currentUtcOffset = getTimezoneOffsetMinutes(settingsStore.appSettings.timeZone);
const transactionTime = parseDateFromUnixTime(transaction.time, transaction.utcOffset, currentUtcOffset);
const transactionYear = getYear(transactionTime);
const transactionMonth = getMonth(transactionTime);
const transactionTime = parseDateTimeFromUnixTime(transaction.time, transaction.utcOffset, currentUtcOffset);
const transactionYear = transactionTime.getGregorianCalendarYear();
const transactionMonth = transactionTime.getGregorianCalendarMonth();
for (let i = 0; i < transactions.value.length; i++) {
const transactionMonthList = transactions.value[i];
@@ -267,7 +261,7 @@ export const useTransactionsStore = defineStore('transactions', () => {
if (transactionYear !== transactionMonthList.year ||
transactionMonth !== transactionMonthList.month ||
transaction.day !== transactionMonthList.items[j].day) {
transaction.gregorianCalendarDayOfMonth !== transactionMonthList.items[j].gregorianCalendarDayOfMonth) {
transactionListStateInvalid.value = true;
return;
}
@@ -346,7 +340,7 @@ export const useTransactionsStore = defineStore('transactions', () => {
for (let i = 0; i < transactionMonthList.items.length; i++) {
const transaction = transactionMonthList.items[i];
const transactionDay = isNumber(transaction.day) ? transaction.day.toString() : '0';
const transactionDay = isNumber(transaction.gregorianCalendarDayOfMonth) ? transaction.gregorianCalendarDayOfMonth.toString() : '0';
let dailyTotalAmount = dailyTotalAmounts[transactionDay];
if (!dailyTotalAmount) {
@@ -450,8 +444,8 @@ export const useTransactionsStore = defineStore('transactions', () => {
return;
}
const transactionTime = parseDateFromUnixTime(transaction.time, transaction.utcOffset, currentUtcOffset);
transaction.setDisplayDate(getShortDate(transactionTime), getDay(transactionTime), getDayOfWeekName(transactionTime));
const transactionTime = parseDateTimeFromUnixTime(transaction.time, transaction.utcOffset, currentUtcOffset);
transaction.setDisplayDate(transactionTime.getGregorianCalendarYearDashMonthDashDay(), transactionTime.getGregorianCalendarDay(), transactionTime.getWeekDay());
if (transaction.sourceAccountId) {
transaction.setSourceAccount(accountsStore.allAccountsMap[transaction.sourceAccountId]);
@@ -23,9 +23,8 @@ import { replaceAll } from '@/lib/common.ts';
import {
getUtcOffsetByUtcOffsetMinutes,
getTimezoneOffsetMinutes,
parseDateFromUnixTime,
formatUnixTime,
getUnixTime
parseDateTimeFromUnixTime,
formatUnixTime
} from '@/lib/datetime.ts';
export function useReconciliationStatementPageBase() {
@@ -132,8 +131,7 @@ export function useReconciliationStatementPageBase() {
}
function getDisplayDateTime(transaction: TransactionReconciliationStatementResponseItem): string {
const transactionTime = getUnixTime(parseDateFromUnixTime(transaction.time, transaction.utcOffset, currentTimezoneOffsetMinutes.value));
return formatUnixTimeToLongDateTime(transactionTime);
return formatUnixTimeToLongDateTime(transaction.time, transaction.utcOffset, currentTimezoneOffsetMinutes.value);
}
function getDisplayDate(transaction: TransactionReconciliationStatementResponseItem): string {
@@ -210,7 +208,7 @@ export function useReconciliationStatementPageBase() {
const transactions = reconciliationStatements.value?.transactions ?? [];
const rows = transactions.map(transaction => {
const transactionTime = getUnixTime(parseDateFromUnixTime(transaction.time, transaction.utcOffset, currentTimezoneOffsetMinutes.value));
const transactionTime = parseDateTimeFromUnixTime(transaction.time, transaction.utcOffset, currentTimezoneOffsetMinutes.value).getUnixTime();
const type = getDisplayTransactionType(transaction);
let categoryName = allCategoriesMap.value[transaction.categoryId]?.name || '';
let displayAmount = formatAmountToWesternArabicNumeralsWithoutDigitGrouping(transaction.sourceAmount);
@@ -10,7 +10,7 @@ import { useTransactionTagsStore } from '@/stores/transactionTag.ts';
import { type TransactionListFilter, type TransactionMonthList, useTransactionsStore } from '@/stores/transaction.ts';
import type { TypeAndName } from '@/core/base.ts';
import { type LocalizedDateRange, type WeekDayValue, DateRange, DateRangeScene } from '@/core/datetime.ts';
import { type TextualYearMonthDay, type Year0BasedMonth, type LocalizedDateRange, type WeekDayValue, DateRange, DateRangeScene } from '@/core/datetime.ts';
import { AccountType } from '@/core/account.ts';
import { TransactionType } from '@/core/transaction.ts';
import { DISPLAY_HIDDEN_AMOUNT, INCOMPLETE_AMOUNT_SUFFIX } from '@/consts/numeral.ts';
@@ -28,14 +28,10 @@ import {
getLocalDatetimeFromUnixTime,
getActualUnixTimeForStore,
getDummyUnixTimeForLocalUsage,
getCurrentYearAndMonth,
parseDateFromUnixTime,
getYearAndMonth,
getYear,
getMonth,
getCurrentDateTime,
parseDateTimeFromUnixTime,
getYearMonthFirstUnixTime,
getDay,
getUnixTime,
getUnixTimeFromLocalDatetime,
isDateRangeMatchOneMonth
} from '@/lib/datetime.ts';
@@ -99,7 +95,7 @@ export function useTransactionListPageBase() {
const loading = ref<boolean>(true);
const customMinDatetime = ref<number>(0);
const customMaxDatetime = ref<number>(0);
const currentCalendarDate = ref<string>('');
const currentCalendarDate = ref<TextualYearMonthDay | ''>('');
const currentTimezoneOffsetMinutes = computed<number>(() => getTimezoneOffsetMinutes(settingsStore.appSettings.timeZone));
const firstDayOfWeek = computed<WeekDayValue>(() => userStore.currentUserFirstDayOfWeek);
@@ -175,12 +171,12 @@ export function useTransactionListPageBase() {
const queryMinTime = computed<string>(() => formatUnixTimeToLongDateTime(query.value.minTime));
const queryMaxTime = computed<string>(() => formatUnixTimeToLongDateTime(query.value.maxTime));
const queryMonthlyData = computed<boolean>(() => isDateRangeMatchOneMonth(query.value.minTime, query.value.maxTime));
const queryMonth = computed<string>(() => {
const queryMonth = computed<Year0BasedMonth>(() => {
if (!query.value.minTime || !query.value.maxTime) {
return getCurrentYearAndMonth();
return getCurrentDateTime().toGregorianCalendarYear0BasedMonth();
}
return getYearAndMonth(parseDateFromUnixTime(query.value.minTime));
return parseDateTimeFromUnixTime(query.value.minTime).toGregorianCalendarYear0BasedMonth();
});
const queryAllFilterCategoryIds = computed<Record<string, boolean>>(() => transactionsStore.allFilterCategoryIds);
@@ -248,9 +244,9 @@ export function useTransactionListPageBase() {
return null;
}
const currentMonthMinDate = parseDateFromUnixTime(query.value.minTime);
const currentYear = getYear(currentMonthMinDate);
const currentMonth = getMonth(currentMonthMinDate);
const currentMonthMinDate = parseDateTimeFromUnixTime(query.value.minTime);
const currentYear = currentMonthMinDate.getGregorianCalendarYear();
const currentMonth = currentMonthMinDate.getGregorianCalendarMonth();
for (let i = 0; i < allTransactions.length; i++) {
if (allTransactions[i].year === currentYear && allTransactions[i].month === currentMonth) {
@@ -262,8 +258,8 @@ export function useTransactionListPageBase() {
});
function noTransactionInMonthDay(date: Date): boolean {
const dateTime = parseDateFromUnixTime(getActualUnixTimeForStore(getUnixTime(date), getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes()));
return !currentMonthTransactionData.value || !currentMonthTransactionData.value.dailyTotalAmounts || !currentMonthTransactionData.value.dailyTotalAmounts[getDay(dateTime)];
const dateTime = parseDateTimeFromUnixTime(getActualUnixTimeForStore(getUnixTimeFromLocalDatetime(date), getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes()));
return !currentMonthTransactionData.value || !currentMonthTransactionData.value.dailyTotalAmounts || !currentMonthTransactionData.value.dailyTotalAmounts[dateTime.getGregorianCalendarDay()];
}
const canAddTransaction = computed<boolean>(() => {
@@ -291,12 +287,11 @@ export function useTransactionListPageBase() {
}
function getDisplayLongDate(transaction: Transaction): string {
const transactionTime = getUnixTime(parseDateFromUnixTime(transaction.time, transaction.utcOffset, currentTimezoneOffsetMinutes.value));
return formatUnixTimeToLongDate(transactionTime);
return formatUnixTimeToLongDate(transaction.time, transaction.utcOffset, currentTimezoneOffsetMinutes.value);
}
function getDisplayLongYearMonth(transactionMonthList: TransactionMonthList): string {
return formatUnixTimeToLongYearMonth(getYearMonthFirstUnixTime(transactionMonthList.yearMonth));
return formatUnixTimeToLongYearMonth(getYearMonthFirstUnixTime(transactionMonthList.yearDashMonth));
}
function getDisplayTimezone(transaction: Transaction): string {
@@ -41,10 +41,7 @@ import { DISPLAY_HIDDEN_AMOUNT, INCOMPLETE_AMOUNT_SUFFIX } from '@/consts/numera
import { type TransactionMonthlyIncomeAndExpenseData } from '@/models/transaction.ts';
import {
parseDateFromUnixTime,
getMonthName
} from '@/lib/datetime.ts';
import { parseDateTimeFromUnixTime } from '@/lib/datetime.ts';
import { getExpenseAndIncomeAmountColor } from '@/lib/ui/common.ts';
export interface MonthlyIncomeAndExpenseCardClickEvent {
@@ -100,7 +97,7 @@ const chartOptions = computed<object>(() => {
if (props.data) {
for (let i = 0; i < props.data.length; i++) {
const item = props.data[i];
const month = getMonthName(parseDateFromUnixTime(item.monthStartTime));
const month = parseDateTimeFromUnixTime(item.monthStartTime).getGregorianCalendarMonthName();
monthNames.push(getMonthShortName(month));
incomeAmounts.push(item.incomeAmount);
@@ -358,7 +358,7 @@ import { useTransactionCategoriesStore } from '@/stores/transactionCategory.ts';
import { type TransactionStatisticsPartialFilter, useStatisticsStore } from '@/stores/statistics.ts';
import type { TypeAndDisplayName } from '@/core/base.ts';
import { type TimeRangeAndDateType, DateRangeScene, DateRange } from '@/core/datetime.ts';
import { type TextualYearMonth, type TimeRangeAndDateType, DateRangeScene, DateRange } from '@/core/datetime.ts';
import { ThemeType } from '@/core/theme.ts';
import {
StatisticsAnalysisType,
@@ -375,7 +375,7 @@ import {
arrayItemToObjectField
} from '@/lib/common.ts';
import {
getYearAndMonthFromUnixTime,
getGregorianCalendarYearAndMonthFromUnixTime,
getYearMonthFirstUnixTime,
getYearMonthLastUnixTime,
getShiftedDateRangeAndDateType,
@@ -407,8 +407,8 @@ interface TransactionStatisticsProps {
initChartDataType?: string,
initChartType?: string,
initChartDateType?: string,
initStartTime?: string,
initEndTime?: string,
initStartTime?: TextualYearMonth | '',
initEndTime?: TextualYearMonth | '',
initFilterAccountIds?: string,
initFilterCategoryIds?: string,
initTagIds?: string,
@@ -814,8 +814,8 @@ function setDateFilter(dateType: number): void {
} else if (analysisType.value === StatisticsAnalysisType.TrendAnalysis) {
changed = statisticsStore.updateTransactionStatisticsFilter({
trendChartDateType: dateRange.dateType,
trendChartStartYearMonth: getYearAndMonthFromUnixTime(dateRange.minTime),
trendChartEndYearMonth: getYearAndMonthFromUnixTime(dateRange.maxTime)
trendChartStartYearMonth: getGregorianCalendarYearAndMonthFromUnixTime(dateRange.minTime),
trendChartEndYearMonth: getGregorianCalendarYearAndMonthFromUnixTime(dateRange.maxTime)
});
}
@@ -826,7 +826,7 @@ function setDateFilter(dateType: number): void {
}
}
function setCustomDateFilter(startTime: number | string, endTime: number | string): void {
function setCustomDateFilter(startTime: number | TextualYearMonth, endTime: number | TextualYearMonth): void {
if (!startTime || !endTime) {
return;
}
@@ -882,8 +882,8 @@ function shiftDateRange(scale: number): void {
changed = statisticsStore.updateTransactionStatisticsFilter({
trendChartDateType: newDateRange.dateType,
trendChartStartYearMonth: getYearAndMonthFromUnixTime(newDateRange.minTime),
trendChartEndYearMonth: getYearAndMonthFromUnixTime(newDateRange.maxTime)
trendChartStartYearMonth: getGregorianCalendarYearAndMonthFromUnixTime(newDateRange.minTime),
trendChartEndYearMonth: getGregorianCalendarYearAndMonthFromUnixTime(newDateRange.maxTime)
});
}
@@ -992,8 +992,8 @@ onBeforeRouteUpdate((to) => {
initChartDataType: (to.query['chartDataType'] as string | null) || undefined,
initChartType: (to.query['chartType'] as string | null) || undefined,
initChartDateType: (to.query['chartDateType'] as string | null) || undefined,
initStartTime: (to.query['startTime'] as string | null) || undefined,
initEndTime: (to.query['endTime'] as string | null) || undefined,
initStartTime: (to.query['startTime'] as TextualYearMonth | null) || undefined,
initEndTime: (to.query['endTime'] as TextualYearMonth | null) || undefined,
initFilterAccountIds: (to.query['filterAccountIds'] as string | null) || undefined,
initFilterCategoryIds: (to.query['filterCategoryIds'] as string | null) || undefined,
initTagIds: (to.query['tagIds'] as string | null) || undefined,
+11 -12
View File
@@ -165,7 +165,7 @@
</v-card-text>
<v-card-text class="transaction-calendar-container pt-0" v-if="pageType === TransactionListPageType.Calendar.type">
<vue-date-picker inline auto-apply model-type="yyyy-M-d"
<vue-date-picker inline auto-apply model-type="yyyy-MM-dd"
month-name-format="long"
:config="{ noSwipe: true }"
:readonly="loading"
@@ -545,13 +545,13 @@
:class="{ 'disabled': loading, 'has-bottom-border': idx < transactions.length - 1 }"
v-for="(transaction, idx) in transactions">
<tr class="transaction-list-row-date no-hover text-sm"
v-if="pageType === TransactionListPageType.List.type && (idx === 0 || (idx > 0 && (transaction.date !== transactions[idx - 1].date)))">
v-if="pageType === TransactionListPageType.List.type && (idx === 0 || (idx > 0 && (transaction.gregorianCalendarYearDashMonthDashDay !== transactions[idx - 1].gregorianCalendarYearDashMonthDashDay)))">
<td :colspan="showTagInTransactionListPage ? 6 : 5" class="font-weight-bold">
<div class="d-flex align-center">
<span>{{ getDisplayLongDate(transaction) }}</span>
<v-chip class="ms-1" color="default" size="x-small"
v-if="transaction.dayOfWeek">
{{ getWeekdayLongName(transaction.dayOfWeek) }}
v-if="transaction.displayDayOfWeek">
{{ getWeekdayLongName(transaction.displayDayOfWeek) }}
</v-chip>
</div>
</td>
@@ -689,6 +689,7 @@ import { useDesktopPageStore } from '@/stores/desktopPage.ts';
import type { TypeAndDisplayName } from '@/core/base.ts';
import {
type Year0BasedMonth,
type LocalizedRecentMonthDateRange,
type TimeRangeAndDateType,
DateRangeScene,
@@ -710,9 +711,7 @@ import {
} from '@/lib/common.ts';
import {
getCurrentUnixTime,
parseDateFromUnixTime,
getYear,
getMonth,
parseDateTimeFromUnixTime,
getBrowserTimezoneOffsetMinutes,
getActualUnixTimeForStore,
getDayFirstUnixTimeBySpecifiedUnixTime,
@@ -960,7 +959,7 @@ const transactions = computed<Transaction[]>(() => {
for (let i = 0; i < transactionData.items.length; i++) {
const transaction = transactionData.items[i];
if (transaction.date === currentCalendarDate.value) {
if (transaction.gregorianCalendarYearDashMonthDashDay === currentCalendarDate.value) {
transactions.push(transaction);
}
}
@@ -1208,9 +1207,9 @@ function reload(force: boolean, init: boolean): void {
}
if (queryMonthlyData.value) {
const currentMonthMinDate = parseDateFromUnixTime(query.value.minTime);
const currentYear = getYear(currentMonthMinDate);
const currentMonth = getMonth(currentMonthMinDate);
const currentMonthMinDate = parseDateTimeFromUnixTime(query.value.minTime);
const currentYear = currentMonthMinDate.getGregorianCalendarYear();
const currentMonth = currentMonthMinDate.getGregorianCalendarMonth();
return transactionsStore.loadMonthlyAllTransactions({
year: currentYear,
@@ -1362,7 +1361,7 @@ function changeCustomDateFilter(minTime: number, maxTime: number): void {
updateUrlWhenChanged(changed);
}
function changeCustomMonthDateFilter(yearMonth: string): void {
function changeCustomMonthDateFilter(yearMonth: Year0BasedMonth): void {
if (!yearMonth) {
return;
}
@@ -936,8 +936,6 @@ import {
import { generateRandomUUID } from '@/lib/misc.ts';
import logger from '@/lib/logger.ts';
import {
parseDateFromUnixTime,
getUnixTime,
getUtcOffsetByUtcOffsetMinutes,
getTimezoneOffsetMinutes
} from '@/lib/datetime.ts';
@@ -1655,8 +1653,7 @@ function isTagValid(tagIds: string[], tagIndex: number): boolean {
}
function getDisplayDateTime(transaction: ImportTransaction): string {
const transactionTime = getUnixTime(parseDateFromUnixTime(transaction.time, transaction.utcOffset, currentTimezoneOffsetMinutes.value));
return formatUnixTimeToLongDateTime(transactionTime);
return formatUnixTimeToLongDateTime(transaction.time, transaction.utcOffset, currentTimezoneOffsetMinutes.value);
}
function getDisplayTimezone(transaction: ImportTransaction): string {
@@ -125,7 +125,7 @@ import { useSettingsStore } from '@/stores/setting.ts';
import { TextDirection } from '@/core/text.ts';
import { FontSize } from '@/core/font.ts';
import { getLocalDatetimeFromUnixTime, getCurrentUnixTime, getDay, getDayOfWeekName } from '@/lib/datetime.ts';
import { parseDateTimeFromUnixTime, getCurrentUnixTime } from '@/lib/datetime.ts';
import { setAppFontSize, getFontSizePreviewClassName } from '@/lib/ui/mobile.ts';
const props = defineProps<{
@@ -149,8 +149,8 @@ const fontSize = ref<number>(settingsStore.appSettings.fontSize);
const textDirection = computed<string>(() => getCurrentLanguageTextDirection());
const fontSizePreviewClassName = computed<string>(() => getFontSizePreviewClassName(fontSize.value));
const currentLongYearMonth = computed<string>(() => formatUnixTimeToLongYearMonth(currentUnixTime.value));
const currentDayOfMonth = computed<number>(() => getDay(getLocalDatetimeFromUnixTime(currentUnixTime.value)));
const currentDayOfWeek = computed<string>(() => getWeekdayShortName(getDayOfWeekName(getLocalDatetimeFromUnixTime(currentUnixTime.value))));
const currentDayOfMonth = computed<number>(() => parseDateTimeFromUnixTime(currentUnixTime.value).getLocalizedCalendarDay());
const currentDayOfWeek = computed<string>(() => getWeekdayShortName(parseDateTimeFromUnixTime(currentUnixTime.value).getWeekDay()));
const currentShortTime = computed<string>(() => formatUnixTimeToShortTime(currentUnixTime.value));
function getFontSizeName(): string {
@@ -344,7 +344,7 @@ import { useStatisticsStore } from '@/stores/statistics.ts';
import type { TypeAndDisplayName } from '@/core/base.ts';
import { TextDirection } from '@/core/text.ts';
import { type TimeRangeAndDateType, DateRangeScene, DateRange } from '@/core/datetime.ts';
import { type TextualYearMonth, type TimeRangeAndDateType, DateRangeScene, DateRange } from '@/core/datetime.ts';
import {
StatisticsAnalysisType,
CategoricalChartType,
@@ -355,7 +355,7 @@ import {
import { isString, isNumber } from '@/lib/common.ts';
import {
getYearAndMonthFromUnixTime,
getGregorianCalendarYearAndMonthFromUnixTime,
getYearMonthFirstUnixTime,
getYearMonthLastUnixTime,
getShiftedDateRangeAndDateType,
@@ -626,8 +626,8 @@ function setDateFilter(dateType: number): void {
} else if (analysisType.value === StatisticsAnalysisType.TrendAnalysis) {
changed = statisticsStore.updateTransactionStatisticsFilter({
trendChartDateType: dateRange.dateType,
trendChartStartYearMonth: getYearAndMonthFromUnixTime(dateRange.minTime),
trendChartEndYearMonth: getYearAndMonthFromUnixTime(dateRange.maxTime)
trendChartStartYearMonth: getGregorianCalendarYearAndMonthFromUnixTime(dateRange.minTime),
trendChartEndYearMonth: getGregorianCalendarYearAndMonthFromUnixTime(dateRange.maxTime)
});
}
@@ -638,7 +638,7 @@ function setDateFilter(dateType: number): void {
}
}
function setCustomDateFilter(startTime: number | string, endTime: number | string): void {
function setCustomDateFilter(startTime: number | TextualYearMonth, endTime: number | TextualYearMonth): void {
if (!startTime || !endTime) {
return;
}
@@ -692,8 +692,8 @@ function shiftDateRange(scale: number): void {
changed = statisticsStore.updateTransactionStatisticsFilter({
trendChartDateType: newDateRange.dateType,
trendChartStartYearMonth: getYearAndMonthFromUnixTime(newDateRange.minTime),
trendChartEndYearMonth: getYearAndMonthFromUnixTime(newDateRange.maxTime)
trendChartStartYearMonth: getGregorianCalendarYearAndMonthFromUnixTime(newDateRange.minTime),
trendChartEndYearMonth: getGregorianCalendarYearAndMonthFromUnixTime(newDateRange.maxTime)
});
}
+3 -3
View File
@@ -536,7 +536,7 @@ const {
getMultiWeekdayLongNames,
formatUnixTimeToLongDate,
formatUnixTimeToLongTime,
formatDateToLongDate
formatGregorianCalendarYearDashMonthDashDayToLongDate
} = useI18n();
const { showAlert, showConfirm, showToast, routeBackOnError } = useI18nUIComponents();
@@ -754,7 +754,7 @@ const transactionDisplayScheduledStartDate = computed<string>(() => {
const template = transaction.value as TransactionTemplate;
if (template.scheduledStartDate) {
return formatDateToLongDate(template.scheduledStartDate);
return formatGregorianCalendarYearDashMonthDashDayToLongDate(template.scheduledStartDate);
} else {
return tt('No limit');
}
@@ -768,7 +768,7 @@ const transactionDisplayScheduledEndDate = computed<string>(() => {
const template = transaction.value as TransactionTemplate;
if (template.scheduledEndDate) {
return formatDateToLongDate(template.scheduledEndDate);
return formatGregorianCalendarYearDashMonthDashDayToLongDate(template.scheduledEndDate);
} else {
return tt('No limit');
}
+36 -36
View File
@@ -67,7 +67,7 @@
</f7-toolbar>
<f7-block class="transaction-calendar-container margin-vertical" v-if="pageType === TransactionListPageType.Calendar.type">
<vue-date-picker inline auto-apply model-type="yyyy-M-d"
<vue-date-picker inline auto-apply model-type="yyyy-MM-dd"
month-name-format="long"
class="justify-content-center"
:config="{ noSwipe: true }"
@@ -174,13 +174,13 @@
</f7-list>
<f7-block class="combination-list-wrapper margin-vertical" :class="{ 'no-accordion-toggle': pageType !== TransactionListPageType.List.type }"
:key="transactionMonthList.yearMonth" v-for="(transactionMonthList) in transactions">
:key="transactionMonthList.yearDashMonth" v-for="(transactionMonthList) in transactions">
<f7-accordion-item :opened="transactionMonthList.opened"
@accordion:open="collapseTransactionMonthList(transactionMonthList, false)"
@accordion:opened="onTransactionMonthListCollapseStateChanged"
@accordion:close="collapseTransactionMonthList(transactionMonthList, true)"
@accordion:closed="onTransactionMonthListCollapseStateChanged">
<f7-block-title :id="getTransactionMonthTitleDomId(transactionMonthList.yearMonth)" v-if="pageType === TransactionListPageType.List.type">
<f7-block-title :id="getTransactionMonthTitleDomId(transactionMonthList.yearDashMonth)" v-if="pageType === TransactionListPageType.List.type">
<f7-accordion-toggle>
<f7-list strong inset dividers media-list
class="transaction-amount-list combination-list-header"
@@ -209,7 +209,7 @@
v-if="isTransactionMonthListInvisible(transactionMonthList)" />
<f7-list strong inset dividers media-list accordion-list
class="transaction-info-list transaction-month-list combination-list-content"
:id="getTransactionMonthListDomId(transactionMonthList.yearMonth)"
:id="getTransactionMonthListDomId(transactionMonthList.yearDashMonth)"
v-if="!isTransactionMonthListInvisible(transactionMonthList)"
>
<f7-list-item swipeout chevron-center accordion-item
@@ -222,10 +222,10 @@
<template #media>
<div class="display-flex flex-direction-column transaction-date" :style="getTransactionDateStyle(transaction, idx > 0 ? transactionMonthList.items[idx - 1] : null)">
<span class="transaction-day full-line flex-direction-column">
{{ transaction.day }}
{{ transaction.gregorianCalendarDayOfMonth }}
</span>
<span class="transaction-day-of-week full-line flex-direction-column" v-if="transaction.dayOfWeek">
{{ getWeekdayShortName(transaction.dayOfWeek) }}
<span class="transaction-day-of-week full-line flex-direction-column" v-if="transaction.displayDayOfWeek">
{{ getWeekdayShortName(transaction.displayDayOfWeek) }}
</span>
</div>
</template>
@@ -620,9 +620,11 @@ import { type TransactionMonthList, useTransactionsStore } from '@/stores/transa
import type { TypeAndDisplayName } from '@/core/base.ts';
import { TextDirection } from '@/core/text.ts';
import {
type TextualYearMonth,
type Year0BasedMonth,
type TimeRangeAndDateType,
DateRangeScene,
DateRange,
DateRange
} from '@/core/datetime.ts';
import { AmountFilterType } from '@/core/numeral.ts';
import { TransactionType } from '@/core/transaction.ts';
@@ -635,11 +637,9 @@ import {
} from '@/lib/common.ts';
import {
getCurrentUnixTime,
parseDateFromUnixTime,
parseDateTimeFromUnixTime,
getBrowserTimezoneOffsetMinutes,
getActualUnixTimeForStore,
getYear,
getMonth,
getDayFirstUnixTimeBySpecifiedUnixTime,
getYearMonthFirstUnixTime,
getYearMonthLastUnixTime,
@@ -731,8 +731,8 @@ const transactionsStore = useTransactionsStore();
const loadingError = ref<unknown | null>(null);
const loadingMore = ref<boolean>(false);
const transactionToDelete = ref<Transaction | null>(null);
const transactionInvisibleYearMonths = ref<Record<string, boolean>>({});
const transactionYearMonthListHeights = ref<Record<string, number>>({});
const transactionInvisibleYearMonths = ref<Record<TextualYearMonth, boolean>>({});
const transactionYearMonthListHeights = ref<Record<TextualYearMonth, number>>({});
const showTransactionListPageTypePopover = ref<boolean>(false);
const showDatePopover = ref<boolean>(false);
const showCategoryPopover = ref<boolean>(false);
@@ -768,7 +768,7 @@ const transactions = computed<TransactionMonthList[]>(() => {
for (let i = 0; i < transactionData.items.length; i++) {
const transaction = transactionData.items[i];
if (transaction.date === currentCalendarDate.value) {
if (transaction.gregorianCalendarYearDashMonthDashDay === currentCalendarDate.value) {
transactions.push(transaction);
}
}
@@ -776,7 +776,7 @@ const transactions = computed<TransactionMonthList[]>(() => {
const dailyTransactionList: TransactionMonthList = {
year: currentMonthTransactionData.value.year,
month: currentMonthTransactionData.value.month,
yearMonth: currentMonthTransactionData.value.yearMonth,
yearDashMonth: currentMonthTransactionData.value.yearDashMonth,
opened: true,
items: transactions,
totalAmount: {
@@ -809,11 +809,11 @@ const noTransaction = computed<boolean>(() => {
const hasMoreTransaction = computed<boolean>(() => transactionsStore.hasMoreTransaction);
function getTransactionMonthTitleDomId(yearMonth: string): string {
function getTransactionMonthTitleDomId(yearMonth: TextualYearMonth): string {
return 'transaction_month_title_' + yearMonth;
}
function getTransactionMonthListDomId(yearMonth: string): string {
function getTransactionMonthListDomId(yearMonth: TextualYearMonth): string {
return 'transaction_month_list_' + yearMonth;
}
@@ -822,7 +822,7 @@ function getTransactionDomId(transaction: Transaction): string {
}
function isTransactionMonthListInvisible(transactionMonthList: TransactionMonthList): boolean {
if (!transactionYearMonthListHeights.value[transactionMonthList.yearMonth]) {
if (!transactionYearMonthListHeights.value[transactionMonthList.yearDashMonth]) {
return false;
}
@@ -830,7 +830,7 @@ function isTransactionMonthListInvisible(transactionMonthList: TransactionMonthL
return true;
}
if (transactionInvisibleYearMonths.value[transactionMonthList.yearMonth]) {
if (transactionInvisibleYearMonths.value[transactionMonthList.yearDashMonth]) {
return true;
}
@@ -839,7 +839,7 @@ function isTransactionMonthListInvisible(transactionMonthList: TransactionMonthL
function getTransactionMonthListHeight(transactionMonthList: TransactionMonthList): string {
if (isTransactionMonthListInvisible(transactionMonthList)) {
return transactionYearMonthListHeights.value[transactionMonthList.yearMonth] + 'px';
return transactionYearMonthListHeights.value[transactionMonthList.yearDashMonth] + 'px';
}
return 'auto';
@@ -857,12 +857,12 @@ function setTransactionMonthListHeights(reset: boolean): Promise<unknown> {
for (let i = 0; i < transactions.value.length - 1; i++) {
const transactionMonthList = transactions.value[i];
const yearMonth = transactionMonthList.yearMonth;
const domId = getTransactionMonthListDomId(yearMonth);
const yearDashMonth = transactionMonthList.yearDashMonth;
const domId = getTransactionMonthListDomId(yearDashMonth);
const height = heights[domId];
if (!transactionYearMonthListHeights.value[yearMonth] && isNumber(height)) {
transactionYearMonthListHeights.value[yearMonth] = height;
if (!transactionYearMonthListHeights.value[yearDashMonth] && isNumber(height)) {
transactionYearMonthListHeights.value[yearDashMonth] = height;
}
}
}
@@ -876,30 +876,30 @@ function setTransactionInvisibleYearMonthList(): void {
for (let i = 0; i < transactions.value.length - 1; i++) {
const transactionMonthList = transactions.value[i];
const yearMonth = transactionMonthList.yearMonth;
const yearDashMonth = transactionMonthList.yearDashMonth;
const titleDomId = getTransactionMonthTitleDomId(yearMonth);
const titleDomId = getTransactionMonthTitleDomId(yearDashMonth);
const titleRect = getElementBoundingRect(`#${titleDomId}`);
if (!titleRect) {
continue;
}
const listHeight = transactionYearMonthListHeights.value[yearMonth] || 0;
const listHeight = transactionYearMonthListHeights.value[yearDashMonth] || 0;
const listRectTop = titleRect.top + titleRect.height;
const listRectBottom = listRectTop + listHeight;
const invisible = listRectTop > 2 * window.innerHeight || listRectBottom < -2 * window.innerHeight;
if (invisible) {
transactionInvisibleYearMonths.value[yearMonth] = true;
transactionInvisibleYearMonths.value[yearDashMonth] = true;
} else {
delete transactionInvisibleYearMonths.value[yearMonth];
delete transactionInvisibleYearMonths.value[yearDashMonth];
}
}
}
function getTransactionDateStyle(transaction: Transaction, previousTransaction: Transaction | null): Record<string, string> {
if (!previousTransaction || transaction.day !== previousTransaction.day) {
if (!previousTransaction || transaction.gregorianCalendarDayOfMonth !== previousTransaction.gregorianCalendarDayOfMonth) {
return {};
}
@@ -974,9 +974,9 @@ function reload(done?: () => void): void {
transactionTagsStore.loadAllTags({ force: false })
]).then(() => {
if (queryMonthlyData.value) {
const currentMonthMinDate = parseDateFromUnixTime(query.value.minTime);
const currentYear = getYear(currentMonthMinDate);
const currentMonth = getMonth(currentMonthMinDate);
const currentMonthMinDate = parseDateTimeFromUnixTime(query.value.minTime);
const currentYear = currentMonthMinDate.getGregorianCalendarYear();
const currentMonth = currentMonthMinDate.getGregorianCalendarMonth();
return transactionsStore.loadMonthlyAllTransactions({
year: currentYear,
@@ -1159,7 +1159,7 @@ function changeCustomDateFilter(minTime: number, maxTime: number): void {
}
}
function changeCustomMonthDateFilter(yearMonth: string): void {
function changeCustomMonthDateFilter(yearMonth: Year0BasedMonth): void {
if (!yearMonth) {
return;
}
@@ -1466,8 +1466,8 @@ function collapseTransactionMonthList(monthList: TransactionMonthList, collapse:
collapse: collapse
});
if (!collapse && transactionInvisibleYearMonths.value[monthList.yearMonth]) {
delete transactionInvisibleYearMonths.value[monthList.yearMonth];
if (!collapse && transactionInvisibleYearMonths.value[monthList.yearDashMonth]) {
delete transactionInvisibleYearMonths.value[monthList.yearDashMonth];
}
}