use the daylight saving time zone as default time zone rather than the current standard time zone during the DST

This commit is contained in:
MaysWind
2025-12-24 00:33:47 +08:00
parent c35cbbda15
commit 76af5d946a
96 changed files with 1179 additions and 882 deletions
@@ -17,6 +17,7 @@ import type { TransactionReconciliationStatementResponseItem } from '@/models/tr
import { isArray } from '@/lib/common.ts';
import { sumAmounts } from '@/lib/numeral.ts';
import {
parseDateTimeFromUnixTime,
getGregorianCalendarYearAndMonthFromUnixTime,
getYearFirstUnixTimeBySpecifiedUnixTime,
getQuarterFirstUnixTimeBySpecifiedUnixTime,
@@ -52,11 +53,11 @@ export interface CommonAccountBalanceTrendsChartProps {
export function useAccountBalanceTrendsChartBase(props: CommonAccountBalanceTrendsChartProps) {
const {
formatUnixTimeToShortDate,
formatUnixTimeToGregorianLikeShortYear,
formatUnixTimeToGregorianLikeShortYearMonth,
formatUnixTimeToGregorianLikeYearQuarter,
formatUnixTimeToGregorianLikeFiscalYear
formatDateTimeToShortDate,
formatDateTimeToGregorianLikeShortYear,
formatDateTimeToGregorianLikeShortYearMonth,
formatDateTimeToGregorianLikeYearQuarter,
formatDateTimeToGregorianLikeFiscalYear
} = useI18n();
const dataDateRange = computed<AccountBalanceUnixTimeAndBalanceRange | null>(() => {
@@ -150,19 +151,20 @@ export function useAccountBalanceTrendsChartBase(props: CommonAccountBalanceTren
for (const dateRange of allDateRanges.value) {
const dataItems = dayDataItemsMap[dateRange.minUnixTime];
const minDateTime = parseDateTimeFromUnixTime(dateRange.minUnixTime);
let displayDate = '';
if (props.dateAggregationType === ChartDateAggregationType.Year.type) {
displayDate = formatUnixTimeToGregorianLikeShortYear(dateRange.minUnixTime);
displayDate = formatDateTimeToGregorianLikeShortYear(minDateTime);
} else if (props.dateAggregationType === ChartDateAggregationType.FiscalYear.type) {
displayDate = formatUnixTimeToGregorianLikeFiscalYear(dateRange.minUnixTime);
displayDate = formatDateTimeToGregorianLikeFiscalYear(minDateTime);
} else if (props.dateAggregationType === ChartDateAggregationType.Quarter.type) {
displayDate = formatUnixTimeToGregorianLikeYearQuarter(dateRange.minUnixTime);
displayDate = formatDateTimeToGregorianLikeYearQuarter(minDateTime);
} else if (props.dateAggregationType === ChartDateAggregationType.Month.type) {
displayDate = formatUnixTimeToGregorianLikeShortYearMonth(dateRange.minUnixTime);
displayDate = formatDateTimeToGregorianLikeShortYearMonth(minDateTime);
} else if (props.dateAggregationType === ChartDateAggregationType.Day.type) {
displayDate = formatUnixTimeToShortDate(dateRange.minUnixTime);
displayDate = formatDateTimeToShortDate(minDateTime);
} else {
return ret;
}
+31 -19
View File
@@ -1,16 +1,23 @@
import { ref, computed } from 'vue';
import { type TimeRangeAndDateType, type PresetDateRange, type UnixTimeRange, type WeekDayValue, DateRange } from '@/core/datetime.ts';
import {
type DateTime,
type UnixTimeRange,
type TimeRangeAndDateType,
type PresetDateRange,
type WeekDayValue,
DateRange,
} from '@/core/datetime.ts';
import {
getCurrentUnixTime,
getLocalDatetimeFromUnixTime,
getUnixTimeFromLocalDatetime,
getTodayFirstUnixTime,
getDummyUnixTimeForLocalUsage,
getActualUnixTimeForStore,
getTimezoneOffsetMinutes,
getBrowserTimezoneOffsetMinutes,
getSameDateTimeWithCurrentTimezone,
getSameDateTimeWithBrowserTimezone,
parseDateTimeFromUnixTime,
parseDateTimeFromUnixTimeWithBrowserTimezone,
getDateRangeByDateType
} from '@/lib/datetime.ts';
@@ -45,23 +52,21 @@ function getDateRangeFromProps(props: CommonDateRangeSelectionProps): { minDate:
}
export function useDateRangeSelectionBase(props: CommonDateRangeSelectionProps) {
const { tt, formatUnixTimeToLongDateTime } = useI18n();
const { tt, formatDateTimeToLongDateTime } = useI18n();
const userStore = useUserStore();
const { minDate, maxDate } = getDateRangeFromProps(props);
const dateRange = ref<Date[]>([
getLocalDatetimeFromUnixTime(getDummyUnixTimeForLocalUsage(minDate, getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes())),
getLocalDatetimeFromUnixTime(getDummyUnixTimeForLocalUsage(maxDate, getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes()))
getLocalDatetimeFromSameDateTimeOfUnixTime(minDate),
getLocalDatetimeFromSameDateTimeOfUnixTime(maxDate)
]);
const firstDayOfWeek = computed<WeekDayValue>(() => userStore.currentUserFirstDayOfWeek);
const beginDateTime = computed<string>(() => {
const actualBeginUnixTime = getActualUnixTimeForStore(getUnixTimeFromLocalDatetime(dateRange.value[0] as Date), getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes());
return formatUnixTimeToLongDateTime(actualBeginUnixTime);
return formatDateTimeToLongDateTime(getDateTimeFromSameDateTimeOfLocalDatetime(dateRange.value[0] as Date));
});
const endDateTime = computed<string>(() => {
const actualEndUnixTime = getActualUnixTimeForStore(getUnixTimeFromLocalDatetime(dateRange.value[1] as Date), getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes());
return formatUnixTimeToLongDateTime(actualEndUnixTime);
return formatDateTimeToLongDateTime(getDateTimeFromSameDateTimeOfLocalDatetime(dateRange.value[1] as Date));
});
const presetRanges = computed<PresetDateRange[]>(() => {
const presetRanges:PresetDateRange[] = [];
@@ -82,8 +87,8 @@ export function useDateRangeSelectionBase(props: CommonDateRangeSelectionProps)
presetRanges.push({
label: tt(dateRangeType.name),
value: [
getLocalDatetimeFromUnixTime(getDummyUnixTimeForLocalUsage(dateRange.minTime, getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes())),
getLocalDatetimeFromUnixTime(getDummyUnixTimeForLocalUsage(dateRange.maxTime, getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes()))
getLocalDatetimeFromSameDateTimeOfUnixTime(dateRange.minTime),
getLocalDatetimeFromSameDateTimeOfUnixTime(dateRange.maxTime)
]
});
});
@@ -91,6 +96,14 @@ export function useDateRangeSelectionBase(props: CommonDateRangeSelectionProps)
return presetRanges;
});
function getLocalDatetimeFromSameDateTimeOfUnixTime(unixTime: number): Date {
return getLocalDatetimeFromUnixTime(getSameDateTimeWithBrowserTimezone(parseDateTimeFromUnixTime(unixTime)).getUnixTime());
}
function getDateTimeFromSameDateTimeOfLocalDatetime(localDatetime: Date): DateTime {
return getSameDateTimeWithCurrentTimezone(parseDateTimeFromUnixTimeWithBrowserTimezone(getUnixTimeFromLocalDatetime(localDatetime)));
}
function getFinalDateRange(): UnixTimeRange | null {
if (!dateRange.value[0] || !dateRange.value[1]) {
return null;
@@ -99,16 +112,13 @@ export function useDateRangeSelectionBase(props: CommonDateRangeSelectionProps)
const currentMinDate = dateRange.value[0];
const currentMaxDate = dateRange.value[1];
let minUnixTime = getUnixTimeFromLocalDatetime(currentMinDate);
let maxUnixTime = getUnixTimeFromLocalDatetime(currentMaxDate);
const minUnixTime = getDateTimeFromSameDateTimeOfLocalDatetime(currentMinDate).getUnixTime();
const maxUnixTime = getDateTimeFromSameDateTimeOfLocalDatetime(currentMaxDate).getUnixTime();
if (minUnixTime < 0 || maxUnixTime < 0) {
throw new Error('Date is too early');
}
minUnixTime = getActualUnixTimeForStore(minUnixTime, getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes());
maxUnixTime = getActualUnixTimeForStore(maxUnixTime, getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes());
return {
minUnixTime,
maxUnixTime
@@ -123,6 +133,8 @@ export function useDateRangeSelectionBase(props: CommonDateRangeSelectionProps)
endDateTime,
presetRanges,
// functions
getLocalDatetimeFromSameDateTimeOfUnixTime,
getDateTimeFromSameDateTimeOfLocalDatetime,
getFinalDateRange
};
}
@@ -5,6 +5,15 @@ import { useI18n } from '@/locales/helpers.ts';
import { type NameValue } from '@/core/base.ts';
import { NumeralSystem } from '@/core/numeral.ts';
import {
getLocalDatetimeFromUnixTime,
getUnixTimeFromLocalDatetime,
getSameDateTimeWithBrowserTimezone,
getSameDateTimeWithTimezoneOffset,
parseDateTimeFromUnixTimeWithBrowserTimezone,
parseDateTimeFromUnixTimeWithTimezoneOffset
} from '@/lib/datetime.ts';
export interface TimePickerValue {
value: string;
itemsIndex: number;
@@ -30,6 +39,14 @@ export function useDateTimeSelectionBase() {
const numeralSystem = computed<NumeralSystem>(() => getCurrentNumeralSystemType());
const meridiemItems = computed<NameValue[]>(() => getAllMeridiemIndicators());
function getLocalDatetimeFromSameDateTimeOfUnixTime(unixTime: number, utcOffset: number): Date {
return getLocalDatetimeFromUnixTime(getSameDateTimeWithBrowserTimezone(parseDateTimeFromUnixTimeWithTimezoneOffset(unixTime, utcOffset)).getUnixTime());
}
function getUnixTimeFromSameDateTimeOfLocalDatetime(localDatetime: Date, utcOffset: number): number {
return getSameDateTimeWithTimezoneOffset(parseDateTimeFromUnixTimeWithBrowserTimezone(getUnixTimeFromLocalDatetime(localDatetime)), utcOffset).getUnixTime();
}
function getDisplayTimeValue(value: number, forceTwoDigits: boolean): string {
let textualValue = value.toString();
@@ -89,6 +106,8 @@ export function useDateTimeSelectionBase() {
// computed
meridiemItems,
// functions
getLocalDatetimeFromSameDateTimeOfUnixTime,
getUnixTimeFromSameDateTimeOfLocalDatetime,
getDisplayTimeValue,
generateAllHours,
generateAllMinutesOrSeconds
@@ -7,6 +7,7 @@ import {
getYear0BasedMonthObjectFromString,
getYearMonthStringFromYear0BasedMonthObject,
getCurrentUnixTime,
parseDateTimeFromUnixTime,
getThisYearFirstUnixTime,
getYearMonthFirstUnixTime,
getYearMonthLastUnixTime
@@ -49,7 +50,7 @@ function getMonthRangeFromProps(props: CommonMonthRangeSelectionProps): { minDat
}
export function useMonthRangeSelectionBase(props: CommonMonthRangeSelectionProps) {
const { formatUnixTimeToGregorianLikeLongYearMonth } = useI18n();
const { formatDateTimeToGregorianLikeLongYearMonth } = useI18n();
const { minDate, maxDate } = getMonthRangeFromProps(props);
const dateRange = ref<Year0BasedMonth[]>([
@@ -57,8 +58,8 @@ export function useMonthRangeSelectionBase(props: CommonMonthRangeSelectionProps
maxDate
]);
const beginDateTime = computed<string>(() => formatUnixTimeToGregorianLikeLongYearMonth(getYearMonthFirstUnixTime(dateRange.value[0] as Year0BasedMonth)));
const endDateTime = computed<string>(() => formatUnixTimeToGregorianLikeLongYearMonth(getYearMonthLastUnixTime(dateRange.value[1] as Year0BasedMonth)));
const beginDateTime = computed<string>(() => formatDateTimeToGregorianLikeLongYearMonth(parseDateTimeFromUnixTime(getYearMonthFirstUnixTime(dateRange.value[0] as Year0BasedMonth))));
const endDateTime = computed<string>(() => formatDateTimeToGregorianLikeLongYearMonth(parseDateTimeFromUnixTime(getYearMonthLastUnixTime(dateRange.value[1] as Year0BasedMonth))));
function getFinalMonthRange(): { minYearMonth: TextualYearMonth | '', maxYearMonth: TextualYearMonth | '' } | null {
if (!dateRange.value[0] || !dateRange.value[1]) {
+8 -8
View File
@@ -88,9 +88,9 @@ const {
getCurrentNumeralSystemType,
isLongDateMonthAfterYear,
isLongTime24HourFormat,
getCalendarDisplayShortYearFromUnixTime,
getCalendarDisplayShortMonthFromUnixTime,
getCalendarDisplayDayOfMonthFromUnixTime,
getCalendarDisplayShortYearFromDateTime,
getCalendarDisplayShortMonthFromDateTime,
getCalendarDisplayDayOfMonthFromDateTime,
getCalendarAlternateDate
} = useI18n();
@@ -138,21 +138,21 @@ function switchView(viewType: MenuView): void {
}
function getDisplayYear(year: number): string {
return getCalendarDisplayShortYearFromUnixTime(getYearMonthDayDateTime(year, 1, 1).getUnixTime(), actualNumeralSystem.value);
return getCalendarDisplayShortYearFromDateTime(getYearMonthDayDateTime(year, 1, 1), actualNumeralSystem.value);
}
function getDisplayMonth(month: number): string {
if (isArray(dateTime.value)) {
return getCalendarDisplayShortMonthFromUnixTime(getYearMonthDayDateTime(dateTime.value[0]!.getFullYear(), month + 1, 1).getUnixTime(), actualNumeralSystem.value);
return getCalendarDisplayShortMonthFromDateTime(getYearMonthDayDateTime(dateTime.value[0]!.getFullYear(), month + 1, 1), actualNumeralSystem.value);
} else if (dateTime.value) {
return getCalendarDisplayShortMonthFromUnixTime(getYearMonthDayDateTime(dateTime.value.getFullYear(), month + 1, 1).getUnixTime(), actualNumeralSystem.value);
return getCalendarDisplayShortMonthFromDateTime(getYearMonthDayDateTime(dateTime.value.getFullYear(), month + 1, 1), actualNumeralSystem.value);
} else {
return getCalendarDisplayShortMonthFromUnixTime(getYearMonthDayDateTime(new Date().getFullYear(), month + 1, 1).getUnixTime(), actualNumeralSystem.value);
return getCalendarDisplayShortMonthFromDateTime(getYearMonthDayDateTime(new Date().getFullYear(), month + 1, 1), actualNumeralSystem.value);
}
}
function getDisplayDay(date: Date): string {
return getCalendarDisplayDayOfMonthFromUnixTime(getYearMonthDayDateTime(date.getFullYear(), date.getMonth() + 1, date.getDate()).getUnixTime(), actualNumeralSystem.value);
return getCalendarDisplayDayOfMonthFromDateTime(getYearMonthDayDateTime(date.getFullYear(), date.getMonth() + 1, date.getDate()), actualNumeralSystem.value);
}
defineExpose({
+5 -5
View File
@@ -54,8 +54,8 @@ const emit = defineEmits<{
const {
isLongDateMonthAfterYear,
getCalendarDisplayShortYearFromUnixTime,
getCalendarDisplayShortMonthFromUnixTime
getCalendarDisplayShortYearFromDateTime,
getCalendarDisplayShortMonthFromDateTime
} = useI18n();
const yearRange = getAllowedYearRange();
@@ -96,14 +96,14 @@ function getYear0BasedMonthFromMonthSelectionValue(value: MonthSelectionValue):
}
function getDisplayYear(year: number): string {
return getCalendarDisplayShortYearFromUnixTime(getYearMonthDayDateTime(year, 1, 1).getUnixTime());
return getCalendarDisplayShortYearFromDateTime(getYearMonthDayDateTime(year, 1, 1));
}
function getDisplayMonth(month: number): string {
if (isArray(dateTime.value)) {
return getCalendarDisplayShortMonthFromUnixTime(getYearMonthDayDateTime(dateTime.value[0]!.year, month + 1, 1).getUnixTime());
return getCalendarDisplayShortMonthFromDateTime(getYearMonthDayDateTime(dateTime.value[0]!.year, month + 1, 1));
} else {
return getCalendarDisplayShortMonthFromUnixTime(getYearMonthDayDateTime(dateTime.value.year, month + 1, 1).getUnixTime());
return getCalendarDisplayShortMonthFromDateTime(getYearMonthDayDateTime(dateTime.value.year, month + 1, 1));
}
}
</script>
+4 -12
View File
@@ -38,14 +38,7 @@ import type { CalendarAlternateDate, TextualYearMonthDay, WeekDayValue } from '@
import { INCOMPLETE_AMOUNT_SUFFIX } from '@/consts/numeral.ts';
import { arrangeArrayWithNewStartIndex } from '@/lib/common.ts';
import {
getTimezoneOffsetMinutes,
getBrowserTimezoneOffsetMinutes,
getUnixTimeFromLocalDatetime,
getActualUnixTimeForStore,
getYearMonthDayDateTime,
parseDateTimeFromUnixTime
} from '@/lib/datetime.ts';
import { getYearMonthDayDateTime } from '@/lib/datetime.ts';
const props = defineProps<{
modelValue: TextualYearMonthDay | '';
@@ -67,7 +60,7 @@ const emit = defineEmits<{
const {
getAllLongWeekdayNames,
getAllShortWeekdayNames,
getCalendarDisplayDayOfMonthFromUnixTime,
getCalendarDisplayDayOfMonthFromDateTime,
getCalendarAlternateDates,
formatAmountToLocalizedNumeralsWithCurrency
} = useI18n();
@@ -105,8 +98,7 @@ const alternateDates = computed<Record<TextualYearMonthDay, string> | undefined>
});
function noTransactionInMonthDay(date: Date): boolean {
const dateTime = parseDateTimeFromUnixTime(getActualUnixTimeForStore(getUnixTimeFromLocalDatetime(date), getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes()));
return !props.dailyTotalAmounts || !props.dailyTotalAmounts[dateTime.getGregorianCalendarDay()];
return !props.dailyTotalAmounts || !props.dailyTotalAmounts[date.getDate()];
}
function getDisplayMonthTotalAmount(amount: number, currency: string | false, symbol: string, incomplete: boolean): string {
@@ -115,7 +107,7 @@ function getDisplayMonthTotalAmount(amount: number, currency: string | false, sy
}
function getDisplayDay(date: Date): string {
return getCalendarDisplayDayOfMonthFromUnixTime(getYearMonthDayDateTime(date.getFullYear(), date.getMonth() + 1, date.getDate()).getUnixTime());
return getCalendarDisplayDayOfMonthFromDateTime(getYearMonthDayDateTime(date.getFullYear(), date.getMonth() + 1, date.getDate()));
}
</script>
@@ -43,13 +43,6 @@ import { type CommonDateRangeSelectionProps, useDateRangeSelectionBase } from '@
import { ThemeType } from '@/core/theme.ts';
import {
getLocalDatetimeFromUnixTime,
getDummyUnixTimeForLocalUsage,
getTimezoneOffsetMinutes,
getBrowserTimezoneOffsetMinutes
} from '@/lib/datetime.ts';
interface DesktopDateRangeSelectionProps extends CommonDateRangeSelectionProps {
persistent?: boolean;
}
@@ -64,7 +57,14 @@ const emit = defineEmits<{
const theme = useTheme();
const { tt } = useI18n();
const { dateRange, beginDateTime, endDateTime, presetRanges, getFinalDateRange } = useDateRangeSelectionBase(props);
const {
dateRange,
beginDateTime,
endDateTime,
presetRanges,
getLocalDatetimeFromSameDateTimeOfUnixTime,
getFinalDateRange
} = useDateRangeSelectionBase(props);
const isDarkMode = computed<boolean>(() => theme.global.name.value === ThemeType.Dark);
const showState = computed<boolean>({
@@ -94,13 +94,13 @@ function cancel(): void {
watch(() => props.minTime, (newValue) => {
if (newValue) {
dateRange.value[0] = getLocalDatetimeFromUnixTime(getDummyUnixTimeForLocalUsage(newValue, getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes()));
dateRange.value[0] = getLocalDatetimeFromSameDateTimeOfUnixTime(newValue);
}
});
watch(() => props.maxTime, (newValue) => {
if (newValue) {
dateRange.value[1] = getLocalDatetimeFromUnixTime(getDummyUnixTimeForLocalUsage(newValue, getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes()));
dateRange.value[1] = getLocalDatetimeFromSameDateTimeOfUnixTime(newValue);
}
});
</script>
+12 -12
View File
@@ -94,12 +94,9 @@ import {
} from '@/core/datetime.ts';
import {
getHourIn12HourFormat,
getTimezoneOffsetMinutes,
getBrowserTimezoneOffsetMinutes,
getLocalDatetimeFromUnixTime,
getUnixTimeFromLocalDatetime,
getActualUnixTimeForStore,
getDummyUnixTimeForLocalUsage,
getSameDateTimeWithBrowserTimezone,
parseDateTimeFromUnixTimeWithTimezoneOffset,
parseDateTimeFromKnownDateTimeFormat,
getAMOrPM,
getCombinedDateAndTimeValues
@@ -108,6 +105,7 @@ import { setChildInputFocus } from '@/lib/ui/desktop.ts';
const props = defineProps<{
modelValue: number;
timezoneUtcOffset: number;
disabled?: boolean;
readonly?: boolean;
label?: string;
@@ -124,7 +122,7 @@ const {
getCurrentNumeralSystemType,
parseDateTimeFromLongDateTime,
parseDateTimeFromShortDateTime,
formatUnixTimeToLongDateTime
formatDateTimeToLongDateTime
} = useI18n();
const {
@@ -133,6 +131,8 @@ const {
isMinuteTwoDigits,
isSecondTwoDigits,
isMeridiemIndicatorFirst,
getLocalDatetimeFromSameDateTimeOfUnixTime,
getUnixTimeFromSameDateTimeOfLocalDatetime,
getDisplayTimeValue,
generateAllHours,
generateAllMinutesOrSeconds
@@ -147,10 +147,10 @@ const numeralSystem = computed<NumeralSystem>(() => getCurrentNumeralSystemType(
const dateTime = computed<Date>({
get: () => {
return getLocalDatetimeFromUnixTime(props.modelValue);
return getLocalDatetimeFromSameDateTimeOfUnixTime(props.modelValue, props.timezoneUtcOffset);
},
set: (value: Date) => {
const unixTime = getUnixTimeFromLocalDatetime(value);
const unixTime = getUnixTimeFromSameDateTimeOfLocalDatetime(value, props.timezoneUtcOffset);
if (unixTime < 0) {
emit('error', 'Date is too early');
@@ -161,7 +161,7 @@ const dateTime = computed<Date>({
}
});
const displayTime = computed<string>(() => formatUnixTimeToLongDateTime(getActualUnixTimeForStore(getUnixTimeFromLocalDatetime(dateTime.value), getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes())));
const displayTime = computed<string>(() => formatDateTimeToLongDateTime(parseDateTimeFromUnixTimeWithTimezoneOffset(props.modelValue, props.timezoneUtcOffset)));
const hourItems = computed<TimePickerValue[]>(() => generateAllHours(1, isHourTwoDigits.value));
const minuteItems = computed<TimePickerValue[]>(() => generateAllMinutesOrSeconds(1, isMinuteTwoDigits.value));
@@ -252,7 +252,7 @@ function onPaste(event: ClipboardEvent): void {
dt = parseDateTimeFromKnownDateTimeFormat(text, formats[0] as KnownDateTimeFormat);
if (dt) {
dateTime.value = getLocalDatetimeFromUnixTime(getDummyUnixTimeForLocalUsage(dt.getUnixTime(), getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes()));
dateTime.value = getLocalDatetimeFromUnixTime(getSameDateTimeWithBrowserTimezone(dt).getUnixTime());
return;
}
}
@@ -260,14 +260,14 @@ function onPaste(event: ClipboardEvent): void {
dt = parseDateTimeFromLongDateTime(text);
if (dt) {
dateTime.value = getLocalDatetimeFromUnixTime(getDummyUnixTimeForLocalUsage(dt.getUnixTime(), getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes()));
dateTime.value = getLocalDatetimeFromUnixTime(getSameDateTimeWithBrowserTimezone(dt).getUnixTime());
return;
}
dt = parseDateTimeFromShortDateTime(text);
if (dt) {
dateTime.value = getLocalDatetimeFromUnixTime(getDummyUnixTimeForLocalUsage(dt.getUnixTime(), getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes()));
dateTime.value = getLocalDatetimeFromUnixTime(getSameDateTimeWithBrowserTimezone(dt).getUnixTime());
return;
}
+11 -8
View File
@@ -43,6 +43,7 @@ import {
isNumber
} from '@/lib/common.ts';
import {
parseDateTimeFromUnixTime,
getYearMonthFirstUnixTime,
getYearMonthLastUnixTime,
getDateTypeByDateRange,
@@ -95,11 +96,11 @@ const theme = useTheme();
const {
tt,
getCurrentLanguageTextDirection,
formatUnixTimeToShortDate,
formatUnixTimeToGregorianLikeShortYear,
formatUnixTimeToGregorianLikeShortYearMonth,
formatDateTimeToShortDate,
formatDateTimeToGregorianLikeShortYear,
formatDateTimeToGregorianLikeShortYearMonth,
formatYearQuarterToGregorianLikeYearQuarter,
formatUnixTimeToGregorianLikeFiscalYear,
formatDateTimeToGregorianLikeFiscalYear,
formatAmountToWesternArabicNumeralsWithoutDigitGrouping,
formatAmountToLocalizedNumeralsWithCurrency
} = useI18n();
@@ -151,16 +152,18 @@ const allDisplayDateRanges = computed<string[]>(() => {
const allDisplayDateRanges: string[] = [];
for (const dateRange of allDateRanges.value) {
const minDateTime = parseDateTimeFromUnixTime(dateRange.minUnixTime);
if (props.dateAggregationType === ChartDateAggregationType.Year.type) {
allDisplayDateRanges.push(formatUnixTimeToGregorianLikeShortYear(dateRange.minUnixTime));
allDisplayDateRanges.push(formatDateTimeToGregorianLikeShortYear(minDateTime));
} else if (props.dateAggregationType === ChartDateAggregationType.FiscalYear.type && 'year' in dateRange) {
allDisplayDateRanges.push(formatUnixTimeToGregorianLikeFiscalYear(dateRange.minUnixTime));
allDisplayDateRanges.push(formatDateTimeToGregorianLikeFiscalYear(minDateTime));
} else if (props.dateAggregationType === ChartDateAggregationType.Quarter.type && 'quarter' in dateRange) {
allDisplayDateRanges.push(formatYearQuarterToGregorianLikeYearQuarter(dateRange.year, dateRange.quarter));
} else if (props.dateAggregationType === ChartDateAggregationType.Month.type) {
allDisplayDateRanges.push(formatUnixTimeToGregorianLikeShortYearMonth(dateRange.minUnixTime));
allDisplayDateRanges.push(formatDateTimeToGregorianLikeShortYearMonth(minDateTime));
} else if (props.dateAggregationType === ChartDateAggregationType.Day.type && props.chartMode === 'daily') {
allDisplayDateRanges.push(formatUnixTimeToShortDate(dateRange.minUnixTime));
allDisplayDateRanges.push(formatDateTimeToShortDate(minDateTime));
}
}
@@ -45,13 +45,6 @@ import { type CommonDateRangeSelectionProps, useDateRangeSelectionBase } from '@
import { useEnvironmentsStore } from '@/stores/environment.ts';
import {
getLocalDatetimeFromUnixTime,
getDummyUnixTimeForLocalUsage,
getTimezoneOffsetMinutes,
getBrowserTimezoneOffsetMinutes
} from '@/lib/datetime.ts';
type DateTimePickerType = InstanceType<typeof DateTimePicker>;
const props = defineProps<CommonDateRangeSelectionProps>();
@@ -62,7 +55,14 @@ const emit = defineEmits<{
const { tt } = useI18n();
const { showToast } = useI18nUIComponents();
const { dateRange, beginDateTime, endDateTime, presetRanges, getFinalDateRange } = useDateRangeSelectionBase(props);
const {
dateRange,
beginDateTime,
endDateTime,
presetRanges,
getLocalDatetimeFromSameDateTimeOfUnixTime,
getFinalDateRange
} = useDateRangeSelectionBase(props);
const environmentsStore = useEnvironmentsStore();
@@ -91,11 +91,11 @@ function cancel(): void {
function onSheetOpen(): void {
if (props.minTime) {
dateRange.value[0] = getLocalDatetimeFromUnixTime(getDummyUnixTimeForLocalUsage(props.minTime, getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes()));
dateRange.value[0] = getLocalDatetimeFromSameDateTimeOfUnixTime(props.minTime);
}
if (props.maxTime) {
dateRange.value[1] = getLocalDatetimeFromUnixTime(getDummyUnixTimeForLocalUsage(props.maxTime, getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes()));
dateRange.value[1] = getLocalDatetimeFromSameDateTimeOfUnixTime(props.maxTime);
}
window.dispatchEvent(new Event('resize')); // fix vue-datepicker preset max-width
@@ -111,9 +111,7 @@ import { NumeralSystem } from '@/core/numeral.ts';
import { isDefined } from '@/lib/common.ts';
import {
getHourIn12HourFormat,
getLocalDatetimeFromUnixTime,
getCurrentUnixTime,
getUnixTimeFromLocalDatetime,
getAMOrPM,
getCombinedDateAndTimeValues
} from '@/lib/datetime.ts';
@@ -122,6 +120,7 @@ type DateTimePickerType = InstanceType<typeof DateTimePicker>;
const props = defineProps<{
modelValue: number;
timezoneUtcOffset: number;
initMode?: string;
show: boolean;
}>();
@@ -144,6 +143,8 @@ const {
isSecondTwoDigits,
isMeridiemIndicatorFirst,
meridiemItems,
getLocalDatetimeFromSameDateTimeOfUnixTime,
getUnixTimeFromSameDateTimeOfLocalDatetime,
getDisplayTimeValue,
generateAllHours,
generateAllMinutesOrSeconds
@@ -160,7 +161,7 @@ let resetTimePickerItemPositionItemsLastOffsetTop: number | undefined = undefine
let resetTimePickerItemPositionCheckedFrames: number | undefined = undefined;
const mode = ref<string>(props.initMode || 'time');
const dateTime = ref<Date>(getLocalDatetimeFromUnixTime(props.modelValue || getCurrentUnixTime()));
const dateTime = ref<Date>(getLocalDatetimeFromSameDateTimeOfUnixTime(props.modelValue || getCurrentUnixTime(), props.timezoneUtcOffset));
const timePickerContainerHeight = ref<number | undefined>(undefined);
const timePickerItemHeight = ref<number | undefined>(undefined);
@@ -213,7 +214,7 @@ function switchMode(): void {
}
function setCurrentTime(): void {
dateTime.value = getLocalDatetimeFromUnixTime(getCurrentUnixTime());
dateTime.value = getLocalDatetimeFromSameDateTimeOfUnixTime(getCurrentUnixTime(), props.timezoneUtcOffset);
if (mode.value === 'time') {
scrollAllTimeSelectedItems();
@@ -225,7 +226,7 @@ function confirm(): void {
return;
}
const unixTime = getUnixTimeFromLocalDatetime(dateTime.value);
const unixTime = getUnixTimeFromSameDateTimeOfLocalDatetime(dateTime.value, props.timezoneUtcOffset);
if (unixTime < 0) {
showToast('Date is too early');
@@ -420,7 +421,7 @@ function onSheetOpen(): void {
mode.value = props.initMode || 'time';
if (props.modelValue) {
dateTime.value = getLocalDatetimeFromUnixTime(props.modelValue);
dateTime.value = getLocalDatetimeFromSameDateTimeOfUnixTime(props.modelValue, props.timezoneUtcOffset);
}
if (mode.value === 'time') {
+10 -8
View File
@@ -144,6 +144,7 @@ import {
isNumber
} from '@/lib/common.ts';
import {
parseDateTimeFromUnixTime,
getYearMonthFirstUnixTime,
getYearMonthLastUnixTime,
getDateTypeByDateRange,
@@ -200,11 +201,11 @@ const emit = defineEmits<{
const {
tt,
formatUnixTimeToShortDate,
formatUnixTimeToGregorianLikeShortYear,
formatUnixTimeToGregorianLikeShortYearMonth,
formatDateTimeToShortDate,
formatDateTimeToGregorianLikeShortYear,
formatDateTimeToGregorianLikeShortYearMonth,
formatYearQuarterToGregorianLikeYearQuarter,
formatUnixTimeToGregorianLikeFiscalYear,
formatDateTimeToGregorianLikeFiscalYear,
formatAmountToLocalizedNumeralsWithCurrency
} = useI18n();
@@ -324,18 +325,19 @@ const allDisplayDataItems = computed<TrendsBarChartData>(() => {
dateRangeKey = `${dateRange.year}-${dateRange.month}-${dateRange.day}`;
}
const minDateTime = parseDateTimeFromUnixTime(dateRange.minUnixTime);
let displayDateRange = '';
if (props.dateAggregationType === ChartDateAggregationType.Year.type) {
displayDateRange = formatUnixTimeToGregorianLikeShortYear(dateRange.minUnixTime);
displayDateRange = formatDateTimeToGregorianLikeShortYear(minDateTime);
} else if (props.dateAggregationType === ChartDateAggregationType.FiscalYear.type) {
displayDateRange = formatUnixTimeToGregorianLikeFiscalYear(dateRange.minUnixTime);
displayDateRange = formatDateTimeToGregorianLikeFiscalYear(minDateTime);
} else if (props.dateAggregationType === ChartDateAggregationType.Quarter.type && 'quarter' in dateRange) {
displayDateRange = formatYearQuarterToGregorianLikeYearQuarter(dateRange.year, dateRange.quarter);
} else if (props.dateAggregationType === ChartDateAggregationType.Month.type) {
displayDateRange = formatUnixTimeToGregorianLikeShortYearMonth(dateRange.minUnixTime);
displayDateRange = formatDateTimeToGregorianLikeShortYearMonth(minDateTime);
} else if (props.dateAggregationType === ChartDateAggregationType.Day.type && props.chartMode === 'daily') {
displayDateRange = formatUnixTimeToShortDate(dateRange.minUnixTime);
displayDateRange = formatDateTimeToShortDate(minDateTime);
}
const dataItems = allDateRangeItemsMap[dateRangeKey] || [];
+90 -27
View File
@@ -69,7 +69,31 @@ interface DateTimeFormatResult {
hasNumeral?: boolean;
}
type DateTimeTokenFormatFunction = (d: MomentDateTime, options: DateTimeFormatOptions) => DateTimeFormatResult
type DateTimeTokenFormatFunction = (d: MomentDateTime, options: DateTimeFormatOptions) => DateTimeFormatResult;
const westernmostTimezoneUtcOffset: number = -720; // Etc/GMT+12 (UTC-12:00)
const easternmostTimezoneUtcOffset: number = 840; // Pacific/Kiritimati (UTC+14:00)
function getFixedTimezoneName(utcOffset: number): string {
return `Fixed/Timezone${utcOffset}`;
}
(function initFixedTimezone(): void {
for (let utcOffset = westernmostTimezoneUtcOffset; utcOffset <= easternmostTimezoneUtcOffset; utcOffset += 15) {
const timezoneName = getFixedTimezoneName(utcOffset);
if (moment.tz.zone(timezoneName)) {
continue;
}
moment.tz.add(moment.tz.pack({
name: timezoneName,
abbrs: [`FIX${utcOffset}`],
offsets: [-utcOffset],
untils: [0]
}));
}
})();
class MomentDateTime implements DateTime {
private static readonly tokenFormatFuncs: Record<string, DateTimeTokenFormatFunction> = {
@@ -501,28 +525,29 @@ export function getUtcOffsetByUtcOffsetMinutes(utcOffsetMinutes: number): string
}
}
export function getTimezoneOffset(timezone?: string): string {
return getUtcOffsetByUtcOffsetMinutes(getTimezoneOffsetMinutes(timezone));
export function getTimezoneOffset(unixTime: number, timezone?: string): string {
return getUtcOffsetByUtcOffsetMinutes(getTimezoneOffsetMinutes(unixTime, timezone));
}
export function getTimezoneOffsetMinutes(timezone?: string): number {
export function getTimezoneOffsetMinutes(unixTime: number, timezone?: string): number {
if (timezone) {
return moment().tz(timezone).utcOffset();
return moment.unix(unixTime).tz(timezone).utcOffset();
} else {
return moment().utcOffset();
return moment.unix(unixTime).utcOffset();
}
}
export function getBrowserTimezoneOffset(): string {
return getUtcOffsetByUtcOffsetMinutes(getBrowserTimezoneOffsetMinutes());
export function getBrowserTimezoneOffset(unixTime: number): string {
return getUtcOffsetByUtcOffsetMinutes(getBrowserTimezoneOffsetMinutes(unixTime));
}
export function getBrowserTimezoneOffsetMinutes(): number {
return -new Date().getTimezoneOffset();
export function getBrowserTimezoneOffsetMinutes(unixTime: number): number {
const date = getLocalDatetimeFromUnixTime(getSameDateTimeWithBrowserTimezone(parseDateTimeFromUnixTime(unixTime)).getUnixTime());
return -date.getTimezoneOffset();
}
export function guessTimezoneName(): string {
return moment.tz.guess(true);
export function getBrowserTimezoneName(): string {
return new Intl.DateTimeFormat().resolvedOptions().timeZone;
}
export function getLocalDatetimeFromUnixTime(unixTime: number): Date {
@@ -533,12 +558,46 @@ export function getUnixTimeFromLocalDatetime(datetime: Date): number {
return Math.floor(datetime.getTime() / 1000);
}
export function getActualUnixTimeForStore(unixTime: number, utcOffset: number, currentUtcOffset: number): number {
return unixTime - (utcOffset - currentUtcOffset) * 60;
export function getSameDateTimeWithCurrentTimezone(dateTime: DateTime): DateTime {
const newDateTime = moment().set({
year: dateTime.getGregorianCalendarYear(),
month: dateTime.getGregorianCalendarMonth() - 1,
date: dateTime.getGregorianCalendarDay(),
hour: dateTime.getHour(),
minute: dateTime.getMinute(),
second: dateTime.getSecond(),
millisecond: 0
});
return MomentDateTime.of(newDateTime);
}
export function getDummyUnixTimeForLocalUsage(unixTime: number, utcOffset: number, currentUtcOffset: number): number {
return unixTime + (utcOffset - currentUtcOffset) * 60;
export function getSameDateTimeWithBrowserTimezone(dateTime: DateTime): DateTime {
const newDateTime = moment().tz(getBrowserTimezoneName()).set({
year: dateTime.getGregorianCalendarYear(),
month: dateTime.getGregorianCalendarMonth() - 1,
date: dateTime.getGregorianCalendarDay(),
hour: dateTime.getHour(),
minute: dateTime.getMinute(),
second: dateTime.getSecond(),
millisecond: 0,
});
return MomentDateTime.of(newDateTime);
}
export function getSameDateTimeWithTimezoneOffset(dateTime: DateTime, utcOffset: number): DateTime {
const newDateTime = moment().tz(getFixedTimezoneName(utcOffset)).set({
year: dateTime.getGregorianCalendarYear(),
month: dateTime.getGregorianCalendarMonth() - 1,
date: dateTime.getGregorianCalendarDay(),
hour: dateTime.getHour(),
minute: dateTime.getMinute(),
second: dateTime.getSecond(),
millisecond: 0
});
return MomentDateTime.of(newDateTime);
}
export function getCurrentDateTime(): DateTime {
@@ -554,18 +613,18 @@ export function getYearMonthDayDateTime(year: number, month: number, day: number
return MomentDateTime.of(date);
}
export function parseDateTimeFromUnixTime(unixTime: number, utcOffset?: number, currentUtcOffset?: number): DateTime {
if (isNumber(utcOffset)) {
if (!isNumber(currentUtcOffset)) {
currentUtcOffset = getTimezoneOffsetMinutes();
}
unixTime = getDummyUnixTimeForLocalUsage(unixTime, utcOffset, currentUtcOffset);
}
export function parseDateTimeFromUnixTime(unixTime: number): DateTime {
return MomentDateTime.of(moment.unix(unixTime));
}
export function parseDateTimeFromUnixTimeWithBrowserTimezone(unixTime: number): DateTime {
return MomentDateTime.of(moment.unix(unixTime).tz(getBrowserTimezoneName()));
}
export function parseDateTimeFromUnixTimeWithTimezoneOffset(unixTime: number, utcOffset: number): DateTime {
return MomentDateTime.of(moment.unix(unixTime).tz(getFixedTimezoneName(utcOffset)));
}
export function parseDateTimeFromKnownDateTimeFormat(dateTime: string, format: KnownDateTimeFormat): DateTime | undefined {
const m = moment(dateTime, format.format);
@@ -586,8 +645,12 @@ export function parseDateTimeFromString(dateTime: string, format: string): DateT
return MomentDateTime.of(m);
}
export function formatUnixTime(unixTime: number, format: string, options: DateTimeFormatOptions, utcOffset?: number, currentUtcOffset?: number): string {
return parseDateTimeFromUnixTime(unixTime, utcOffset, currentUtcOffset).format(format, options);
export function formatDateTime(dateTime: DateTime, format: string, options: DateTimeFormatOptions): string {
return dateTime.format(format, options);
}
export function formatUnixTime(unixTime: number, format: string, options: DateTimeFormatOptions): string {
return parseDateTimeFromUnixTime(unixTime).format(format, options);
}
export function formatCurrentTime(format: string, options: DateTimeFormatOptions): string {
+4 -3
View File
@@ -178,7 +178,8 @@ import {
} from './server_settings.ts';
import {
getTimezoneOffsetMinutes,
guessTimezoneName
getBrowserTimezoneName,
getCurrentUnixTime
} from './datetime.ts';
import { generateRandomUUID } from './misc.ts';
import { getBasePath } from './web.ts';
@@ -208,12 +209,12 @@ axios.interceptors.request.use((config: ApiRequestConfig) => {
config.headers.Authorization = `Bearer ${token}`;
}
config.headers['X-Timezone-Offset'] = getTimezoneOffsetMinutes();
config.headers['X-Timezone-Offset'] = getTimezoneOffsetMinutes(getCurrentUnixTime());
let timezoneName = getTimeZone();
if (!timezoneName || timezoneName.trim().length < 1) {
timezoneName = guessTimezoneName();
timezoneName = getBrowserTimezoneName();
}
config.headers['X-Timezone-Name'] = timezoneName;
+5 -10
View File
@@ -11,8 +11,7 @@ import {
isNumber
} from './common.ts';
import {
getBrowserTimezoneOffsetMinutes,
getDummyUnixTimeForLocalUsage
getTimezoneOffsetMinutes
} from './datetime.ts';
import {
categoryTypeToTransactionType,
@@ -33,9 +32,10 @@ export interface SetTransactionOptions {
comment?: string;
}
export function setTransactionModelByTransaction(transaction: Transaction, transaction2: Transaction | null | undefined, allCategories: Record<number, TransactionCategory[]>, allCategoriesMap: Record<string, TransactionCategory>, allVisibleAccounts: Account[], allAccountsMap: Record<string, Account>, allTagsMap: Record<string, TransactionTag>, defaultAccountId: string, options: SetTransactionOptions, setContextData: boolean, convertContextTime: boolean): void {
export function setTransactionModelByTransaction(transaction: Transaction, transaction2: Transaction | null | undefined, allCategories: Record<number, TransactionCategory[]>, allCategoriesMap: Record<string, TransactionCategory>, allVisibleAccounts: Account[], allAccountsMap: Record<string, Account>, allTagsMap: Record<string, TransactionTag>, defaultAccountId: string, options: SetTransactionOptions, setContextData: boolean): void {
if (isDefined(options.time)) {
transaction.time = options.time;
transaction.utcOffset = getTimezoneOffsetMinutes(transaction.time, transaction.timeZone);
}
if (!options.type && options.categoryId && options.categoryId !== '0' && allCategoriesMap[options.categoryId]) {
@@ -172,14 +172,9 @@ export function setTransactionModelByTransaction(transaction: Transaction, trans
}
if (setContextData) {
transaction.utcOffset = transaction2.utcOffset;
transaction.time = transaction2.time;
transaction.timeZone = transaction2.timeZone;
if (convertContextTime) {
transaction.time = getDummyUnixTimeForLocalUsage(transaction2.time, transaction.utcOffset, getBrowserTimezoneOffsetMinutes());
} else {
transaction.time = transaction2.time;
}
transaction.utcOffset = transaction2.utcOffset;
}
transaction.sourceAccountId = transaction2.sourceAccountId;
+37 -45
View File
@@ -187,6 +187,7 @@ import {
formatCurrentTime,
formatGregorianCalendarYearDashMonthDashDay,
formatGregorianCalendarMonthDashDay,
formatDateTime,
formatUnixTime,
getBrowserTimezoneOffset,
getBrowserTimezoneOffsetMinutes,
@@ -202,7 +203,7 @@ import {
getTimeDifferenceHoursAndMinutes,
getTimezoneOffset,
getTimezoneOffsetMinutes,
guessTimezoneName,
getBrowserTimezoneName,
isDateRangeMatchFullMonths,
isDateRangeMatchFullYears,
isPM
@@ -1159,20 +1160,20 @@ export function useI18n() {
return allRecentMonthDateRanges;
}
function getAllTimezones(includeSystemDefault?: boolean): LocalizedTimezoneInfo[] {
function getAllTimezones(unixTime: number, includeSystemDefault?: boolean): LocalizedTimezoneInfo[] {
const numeralSystem = getCurrentNumeralSystemType();
const defaultTimezoneOffset = numeralSystem.replaceWesternArabicDigitsToLocalizedDigits(getBrowserTimezoneOffset());
const defaultTimezoneOffsetMinutes = getBrowserTimezoneOffsetMinutes();
const defaultTimezoneOffset = numeralSystem.replaceWesternArabicDigitsToLocalizedDigits(getBrowserTimezoneOffset(unixTime));
const defaultTimezoneOffsetMinutes = getBrowserTimezoneOffsetMinutes(unixTime);
const allTimezoneInfos: LocalizedTimezoneInfo[] = [];
for (const timezoneInfo of ALL_TIMEZONES) {
const utcOffset = (timezoneInfo.timezoneName !== UTC_TIMEZONE.timezoneName ? numeralSystem.replaceWesternArabicDigitsToLocalizedDigits(getTimezoneOffset(timezoneInfo.timezoneName)) : '');
const utcOffset = (timezoneInfo.timezoneName !== UTC_TIMEZONE.timezoneName ? numeralSystem.replaceWesternArabicDigitsToLocalizedDigits(getTimezoneOffset(unixTime, timezoneInfo.timezoneName)) : '');
const displayName = t(`timezone.${timezoneInfo.displayName}`);
allTimezoneInfos.push({
name: timezoneInfo.timezoneName,
utcOffset: utcOffset,
utcOffsetMinutes: getTimezoneOffsetMinutes(timezoneInfo.timezoneName),
utcOffsetMinutes: getTimezoneOffsetMinutes(unixTime, timezoneInfo.timezoneName),
displayName: displayName,
displayNameWithUtcOffset: `(UTC${utcOffset}) ${displayName}`
});
@@ -1206,7 +1207,7 @@ export function useI18n() {
function getAllTimezoneTypesUsedForStatistics(currentTimezone?: string): TypeAndDisplayName[] {
const numeralSystem = getCurrentNumeralSystemType();
const currentTimezoneOffset = numeralSystem.replaceWesternArabicDigitsToLocalizedDigits(getTimezoneOffset(currentTimezone));
const currentTimezoneOffset = numeralSystem.replaceWesternArabicDigitsToLocalizedDigits(getTimezoneOffset(getCurrentUnixTime(), currentTimezone));
return [
{
@@ -1789,12 +1790,11 @@ export function useI18n() {
return formatGregorianCalendarMonthDashDay(monthDay, getLocalizedLongMonthDayFormat(), getDateTimeFormatOptions({ calendarType: gregorianLikeCalendarType, numeralSystem: numeralSystem }));
}
function formatUnixTimeToGregorianLikeYearQuarter(unixTime: number): string {
function formatDateTimeToGregorianLikeYearQuarter(dateTime: DateTime): string {
const gregorianLikeCalendarType = getGregorianLikeCalendarType();
const dateTimeFormatOptions = getDateTimeFormatOptions({ calendarType: gregorianLikeCalendarType });
const date = parseDateTimeFromUnixTime(unixTime);
const year = date.getLocalizedCalendarYear(dateTimeFormatOptions);
const quarter = date.getLocalizedCalendarQuarter(dateTimeFormatOptions);
const year = dateTime.getLocalizedCalendarYear(dateTimeFormatOptions);
const quarter = dateTime.getLocalizedCalendarQuarter(dateTimeFormatOptions);
return formatYearQuarter(year, quarter);
}
@@ -1887,9 +1887,9 @@ export function useI18n() {
return `${displayStartTime} ~ ${displayEndTime}`;
}
function getTimezoneDifferenceDisplayText(utcOffset: number): string {
function getTimezoneDifferenceDisplayText(unixTime: number, utcOffset: number): string {
const numeralSystem = getCurrentNumeralSystemType();
const defaultTimezoneOffset = getTimezoneOffsetMinutes();
const defaultTimezoneOffset = getTimezoneOffsetMinutes(unixTime);
const offsetTime = getTimeDifferenceHoursAndMinutes(utcOffset - defaultTimezoneOffset);
if (utcOffset > defaultTimezoneOffset) {
@@ -2284,19 +2284,11 @@ export function useI18n() {
}
function setTimeZone(timezone: string): void {
let timezoneOffsetMinutes = getBrowserTimezoneOffsetMinutes();
if (timezone) {
timezoneOffsetMinutes = getTimezoneOffsetMinutes(timezone);
moment.tz.setDefault(timezone);
} else {
moment.tz.setDefault();
}
moment.tz.add(moment.tz.pack({
name: 'Fixed/Timezone',
abbrs: ['FIX'],
offsets: [-timezoneOffsetMinutes],
untils: [0]
}));
moment.tz.setDefault('Fixed/Timezone');
}
function initLocale(lastUserLanguage?: string, timezone?: string): LocaleDefaultSettings | null {
@@ -2317,7 +2309,7 @@ export function useI18n() {
logger.info(`Current timezone is ${timezone}`);
setTimeZone(timezone);
} else {
logger.info(`No timezone is set, use browser default ${getTimezoneOffset()} (maybe ${guessTimezoneName()})`);
logger.info(`No timezone is set, use browser default ${getTimezoneOffset(getCurrentUnixTime())} (${getBrowserTimezoneName()})`);
setTimeZone('');
}
@@ -2423,36 +2415,36 @@ export function useI18n() {
isLongTimeMinuteTwoDigits,
isLongTimeSecondTwoDigits,
// format date time (by calendar display type) functions
getCalendarDisplayShortYearFromUnixTime: (unixTime: number, numeralSystem?: NumeralSystem, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedShortYearFormat(), getDateTimeFormatOptions({ calendarType: getCurrentCalendarDisplayType().primaryCalendarType, numeralSystem: numeralSystem }), utcOffset, currentUtcOffset),
getCalendarDisplayShortMonthFromUnixTime: (unixTime: number, numeralSystem?: NumeralSystem, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, 'MMM', getDateTimeFormatOptions({ calendarType: getCurrentCalendarDisplayType().primaryCalendarType, numeralSystem: numeralSystem }), utcOffset, currentUtcOffset),
getCalendarDisplayDayOfMonthFromUnixTime: (unixTime: number, numeralSystem?: NumeralSystem, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedShortDayFormat(), getDateTimeFormatOptions({ calendarType: getCurrentCalendarDisplayType().primaryCalendarType, numeralSystem: numeralSystem }), utcOffset, currentUtcOffset),
getCalendarDisplayShortYearFromDateTime: (dateTime: DateTime, numeralSystem?: NumeralSystem) => formatDateTime(dateTime, getLocalizedShortYearFormat(), getDateTimeFormatOptions({ calendarType: getCurrentCalendarDisplayType().primaryCalendarType, numeralSystem: numeralSystem })),
getCalendarDisplayShortMonthFromDateTime: (dateTime: DateTime, numeralSystem?: NumeralSystem) => formatDateTime(dateTime, 'MMM', getDateTimeFormatOptions({ calendarType: getCurrentCalendarDisplayType().primaryCalendarType, numeralSystem: numeralSystem })),
getCalendarDisplayDayOfMonthFromDateTime: (dateTime: DateTime, numeralSystem?: NumeralSystem) => formatDateTime(dateTime, getLocalizedShortDayFormat(), getDateTimeFormatOptions({ calendarType: getCurrentCalendarDisplayType().primaryCalendarType, numeralSystem: numeralSystem })),
// format date time (by date display type) functions
parseDateTimeFromLongDateTime: (dateTime: string) => parseDateTimeFromString(dateTime, getLocalizedLongDateFormat() + ' ' + getLocalizedLongTimeFormat()),
parseDateTimeFromShortDateTime: (dateTime: string) => parseDateTimeFromString(dateTime, getLocalizedShortDateFormat() + ' ' + getLocalizedShortTimeFormat()),
formatUnixTimeToLongDateTime: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedLongDateFormat() + ' ' + getLocalizedLongTimeFormat(), getDateTimeFormatOptions(), utcOffset, currentUtcOffset),
formatUnixTimeToShortDateTime: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedShortDateFormat() + ' ' + getLocalizedShortTimeFormat(), getDateTimeFormatOptions(), utcOffset, currentUtcOffset),
formatUnixTimeToLongDate: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedLongDateFormat(), getDateTimeFormatOptions(), utcOffset, currentUtcOffset),
formatUnixTimeToShortDate: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedShortDateFormat(), getDateTimeFormatOptions(), utcOffset, currentUtcOffset),
formatUnixTimeToLongMonthDay: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedLongMonthDayFormat(), getDateTimeFormatOptions(), utcOffset, currentUtcOffset),
formatUnixTimeToShortMonthDay: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedShortMonthDayFormat(), getDateTimeFormatOptions(), utcOffset, currentUtcOffset),
formatUnixTimeToLongTime: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedLongTimeFormat(), getDateTimeFormatOptions(), utcOffset, currentUtcOffset),
formatUnixTimeToShortTime: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedShortTimeFormat(), getDateTimeFormatOptions(), utcOffset, currentUtcOffset),
formatDateTimeToLongDateTime: (dateTime: DateTime) => formatDateTime(dateTime, getLocalizedLongDateFormat() + ' ' + getLocalizedLongTimeFormat(), getDateTimeFormatOptions()),
formatDateTimeToShortDateTime: (dateTime: DateTime) => formatDateTime(dateTime, getLocalizedShortDateFormat() + ' ' + getLocalizedShortTimeFormat(), getDateTimeFormatOptions()),
formatDateTimeToLongDate: (dateTime: DateTime) => formatDateTime(dateTime, getLocalizedLongDateFormat(), getDateTimeFormatOptions()),
formatDateTimeToShortDate: (dateTime: DateTime) => formatDateTime(dateTime, getLocalizedShortDateFormat(), getDateTimeFormatOptions()),
formatDateTimeToLongMonthDay: (dateTime: DateTime) => formatDateTime(dateTime, getLocalizedLongMonthDayFormat(), getDateTimeFormatOptions()),
formatDateTimeToShortMonthDay: (dateTime: DateTime) => formatDateTime(dateTime, getLocalizedShortMonthDayFormat(), getDateTimeFormatOptions()),
formatDateTimeToLongTime: (dateTime: DateTime) => formatDateTime(dateTime, getLocalizedLongTimeFormat(), getDateTimeFormatOptions()),
formatDateTimeToShortTime: (dateTime: DateTime) => formatDateTime(dateTime, getLocalizedShortTimeFormat(), getDateTimeFormatOptions()),
formatGregorianTextualYearMonthDayToLongDate: (date: TextualYearMonthDay) => formatGregorianCalendarYearDashMonthDashDay(date, getLocalizedLongDateFormat(), getDateTimeFormatOptions()),
// format date time (Gregorian calendar and Gregorian-like calendar) functions
formatUnixTimeToGregorianLikeLongYear: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedLongYearFormat(), getDateTimeFormatOptions({ calendarType: getGregorianLikeCalendarType() }), utcOffset, currentUtcOffset),
formatUnixTimeToGregorianLikeShortYear: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedShortYearFormat(), getDateTimeFormatOptions({ calendarType: getGregorianLikeCalendarType() }), utcOffset, currentUtcOffset),
formatUnixTimeToGregorianLikeLongYearMonth: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedLongYearMonthFormat(), getDateTimeFormatOptions({ calendarType: getGregorianLikeCalendarType() }), utcOffset, currentUtcOffset),
formatUnixTimeToGregorianLikeShortYearMonth: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedShortYearMonthFormat(), getDateTimeFormatOptions({ calendarType: getGregorianLikeCalendarType() }), utcOffset, currentUtcOffset),
formatUnixTimeToGregorianLikeLongMonth: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, 'MMMM', getDateTimeFormatOptions({ calendarType: getGregorianLikeCalendarType() }), utcOffset, currentUtcOffset),
formatUnixTimeToGregorianLikeShortMonth: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, 'MMM', getDateTimeFormatOptions({ calendarType: getGregorianLikeCalendarType() }), utcOffset, currentUtcOffset),
formatDateTimeToGregorianLikeLongYear: (dateTime: DateTime) => formatDateTime(dateTime, getLocalizedLongYearFormat(), getDateTimeFormatOptions({ calendarType: getGregorianLikeCalendarType() })),
formatDateTimeToGregorianLikeShortYear: (dateTime: DateTime) => formatDateTime(dateTime, getLocalizedShortYearFormat(), getDateTimeFormatOptions({ calendarType: getGregorianLikeCalendarType() })),
formatDateTimeToGregorianLikeLongYearMonth: (dateTime: DateTime) => formatDateTime(dateTime, getLocalizedLongYearMonthFormat(), getDateTimeFormatOptions({ calendarType: getGregorianLikeCalendarType() })),
formatDateTimeToGregorianLikeShortYearMonth: (dateTime: DateTime) => formatDateTime(dateTime, getLocalizedShortYearMonthFormat(), getDateTimeFormatOptions({ calendarType: getGregorianLikeCalendarType() })),
formatDateTimeToGregorianLikeLongMonth: (dateTime: DateTime) => formatDateTime(dateTime, 'MMMM', getDateTimeFormatOptions({ calendarType: getGregorianLikeCalendarType() })),
formatDateTimeToGregorianLikeShortMonth: (dateTime: DateTime) => formatDateTime(dateTime, 'MMM', getDateTimeFormatOptions({ calendarType: getGregorianLikeCalendarType() })),
formatGregorianTextualMonthDayToGregorianLikeLongMonthDay,
formatUnixTimeToGregorianLikeYearQuarter,
formatDateTimeToGregorianLikeYearQuarter,
formatYearQuarterToGregorianLikeYearQuarter,
formatUnixTimeToGregorianLikeFiscalYear,
formatDateTimeToGregorianLikeFiscalYear: (dateTime: DateTime) => formatUnixTimeToGregorianLikeFiscalYear(dateTime.getUnixTime()),
formatGregorianYearToGregorianLikeFiscalYear,
formatFiscalYearStartToGregorianLikeLongMonth,
// format date time (Gregorian calendar) functions
formatUnixTimeToGregorianDefaultDateTime: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, KnownDateTimeFormat.DefaultDateTime.format, getDateTimeFormatOptions({ numeralSystem: NumeralSystem.WesternArabicNumerals, calendarType: CalendarType.Gregorian }), utcOffset, currentUtcOffset),
formatDateTimeToGregorianDefaultDateTime: (dateTime: DateTime) => formatDateTime(dateTime, KnownDateTimeFormat.DefaultDateTime.format, getDateTimeFormatOptions({ numeralSystem: NumeralSystem.WesternArabicNumerals, calendarType: CalendarType.Gregorian })),
// other format date time functions
formatDateRange,
getTimezoneDifferenceDisplayText,
+18 -19
View File
@@ -226,11 +226,11 @@ export class Transaction implements TransactionInfoResponse {
this._displayDayOfWeek = displayDayOfWeek;
}
public toCreateRequest(clientSessionId: string, actualTime?: number): TransactionCreateRequest {
public toCreateRequest(clientSessionId: string): TransactionCreateRequest {
return {
type: this.type,
categoryId: this.getCategoryId(),
time: actualTime ? actualTime : this.time,
time: this.time,
utcOffset: this.utcOffset,
sourceAccountId: this.sourceAccountId,
destinationAccountId: this.type === TransactionType.Transfer ? this.destinationAccountId : '0',
@@ -245,7 +245,7 @@ export class Transaction implements TransactionInfoResponse {
};
}
public toModifyRequest(actualTime?: number): TransactionModifyRequest {
public toModifyRequest(): TransactionModifyRequest {
let categoryId = this.getCategoryId();
if (this.type === TransactionType.ModifyBalance) {
@@ -255,7 +255,7 @@ export class Transaction implements TransactionInfoResponse {
return {
id: this.id,
categoryId: categoryId,
time: actualTime ? actualTime : this.time,
time: this.time,
utcOffset: this.utcOffset,
sourceAccountId: this.sourceAccountId,
destinationAccountId: this.type === TransactionType.Transfer ? this.destinationAccountId : '0',
@@ -677,20 +677,20 @@ export const ALL_TRANSACTION_AMOUNTS_REQUEST_TYPE = [
export type TransactionAmountsRequestType = typeof ALL_TRANSACTION_AMOUNTS_REQUEST_TYPE[number];
export const LATEST_12MONTHS_TRANSACTION_AMOUNTS_REQUEST_TYPES: PartialRecord<TransactionAmountsRequestType, number> = {
'monthBeforeLast10Months': 11,
'monthBeforeLast9Months': 10,
'monthBeforeLast8Months': 9,
'monthBeforeLast7Months': 8,
'monthBeforeLast6Months': 7,
'monthBeforeLast5Months': 6,
'monthBeforeLast4Months': 5,
'monthBeforeLast3Months': 4,
'monthBeforeLast2Months': 3,
'monthBeforeLastMonth': 2,
'lastMonth': 1,
'thisMonth': 0
};
export const LATEST_12MONTHS_TRANSACTION_AMOUNTS_REQUEST_TYPES: TransactionAmountsRequestType[] = [
'monthBeforeLast10Months',
'monthBeforeLast9Months',
'monthBeforeLast8Months',
'monthBeforeLast7Months',
'monthBeforeLast6Months',
'monthBeforeLast5Months',
'monthBeforeLast4Months',
'monthBeforeLast3Months',
'monthBeforeLast2Months',
'monthBeforeLastMonth',
'lastMonth',
'thisMonth'
];
export interface TransactionAmountsRequestParams extends PartialRecord<TransactionAmountsRequestType, StartEndTime> {
readonly useTransactionTimezone: boolean;
@@ -1009,7 +1009,6 @@ export interface TransactionOverviewResponseItem {
export interface TransactionMonthlyIncomeAndExpenseData {
readonly monthStartTime: number;
readonly monthsBeforeCurrentMonth: number;
readonly incomeAmount: number;
readonly expenseAmount: number;
readonly incompleteIncomeAmount: boolean;
+9 -17
View File
@@ -53,12 +53,7 @@ import {
splitItemsToMap,
countSplitItems
} from '@/lib/common.ts';
import {
getTimezoneOffsetMinutes,
getBrowserTimezoneOffsetMinutes,
getActualUnixTimeForStore,
parseDateTimeFromUnixTime
} from '@/lib/datetime.ts';
import { parseDateTimeFromUnixTimeWithTimezoneOffset } from '@/lib/datetime.ts';
import { getAmountWithDecimalNumberCount } from '@/lib/numeral.ts';
import { getCurrencyFraction } from '@/lib/currency.ts';
import { getFirstVisibleCategoryId } from '@/lib/category.ts';
@@ -185,14 +180,13 @@ export const useTransactionsStore = defineStore('transactions', () => {
}
if (transactionPageWrapper.items && transactionPageWrapper.items.length) {
const currentUtcOffset = getTimezoneOffsetMinutes(settingsStore.appSettings.timeZone);
let currentMonthListIndex = -1;
let currentMonthList: TransactionMonthList | null = null;
for (const [item, index] of itemAndIndex(transactionPageWrapper.items)) {
fillTransactionObject(item, currentUtcOffset);
fillTransactionObject(item);
const transactionTime = parseDateTimeFromUnixTime(item.time, item.utcOffset, currentUtcOffset);
const transactionTime = parseDateTimeFromUnixTimeWithTimezoneOffset(item.time, item.utcOffset);
const transactionYear = transactionTime.getGregorianCalendarYear();
const transactionMonth = transactionTime.getGregorianCalendarMonth();
const transactionYearDashMonth = transactionTime.getGregorianCalendarYearDashMonth();
@@ -264,8 +258,7 @@ export const useTransactionsStore = defineStore('transactions', () => {
}
function updateTransactionInTransactionList({ currentTransaction, defaultCurrency }: { currentTransaction: Transaction, defaultCurrency: string }): void {
const currentUtcOffset = getTimezoneOffsetMinutes(settingsStore.appSettings.timeZone);
const transactionTime = parseDateTimeFromUnixTime(currentTransaction.time, currentTransaction.utcOffset, currentUtcOffset);
const transactionTime = parseDateTimeFromUnixTimeWithTimezoneOffset(currentTransaction.time, currentTransaction.utcOffset);
const transactionYear = transactionTime.getGregorianCalendarYear();
const transactionMonth = transactionTime.getGregorianCalendarMonth();
@@ -276,7 +269,7 @@ export const useTransactionsStore = defineStore('transactions', () => {
for (const [transaction, transactionIndex] of itemAndIndex(transactionMonthList.items)) {
if (transaction.id === currentTransaction.id) {
fillTransactionObject(currentTransaction, currentUtcOffset);
fillTransactionObject(currentTransaction);
if (transactionYear !== transactionMonthList.year ||
transactionMonth !== transactionMonthList.month ||
@@ -445,12 +438,12 @@ export const useTransactionsStore = defineStore('transactions', () => {
}
}
function fillTransactionObject(transaction: Transaction, currentUtcOffset: number): void {
function fillTransactionObject(transaction: Transaction): void {
if (!transaction) {
return;
}
const transactionTime = parseDateTimeFromUnixTime(transaction.time, transaction.utcOffset, currentUtcOffset);
const transactionTime = parseDateTimeFromUnixTimeWithTimezoneOffset(transaction.time, transaction.utcOffset);
transaction.setDisplayDate(transactionTime.getGregorianCalendarYearDashMonthDashDay(), transactionTime.getGregorianCalendarDay(), transactionTime.getWeekDay());
if (transaction.sourceAccountId) {
@@ -1026,7 +1019,6 @@ export const useTransactionsStore = defineStore('transactions', () => {
function saveTransaction({ transaction, defaultCurrency, isEdit, clientSessionId }: { transaction: Transaction, defaultCurrency: string, isEdit: boolean, clientSessionId: string }): Promise<Transaction> {
return new Promise((resolve, reject) => {
const actualTime = getActualUnixTimeForStore(transaction.time, transaction.utcOffset, getBrowserTimezoneOffsetMinutes());
let promise: ApiResponsePromise<TransactionInfoResponse>;
if (transaction.type !== TransactionType.Expense &&
@@ -1041,9 +1033,9 @@ export const useTransactionsStore = defineStore('transactions', () => {
}
if (!isEdit) {
promise = services.addTransaction(transaction.toCreateRequest(clientSessionId, actualTime));
promise = services.addTransaction(transaction.toCreateRequest(clientSessionId));
} else {
promise = services.modifyTransaction(transaction.toModifyRequest(actualTime));
promise = services.modifyTransaction(transaction.toModifyRequest());
}
promise.then(response => {
+4 -2
View File
@@ -9,6 +9,7 @@ import type { VersionInfo } from '@/core/version.ts';
import type { LatestExchangeRateResponse } from '@/models/exchange_rate.ts';
import { parseDateTimeFromUnixTime } from '@/lib/datetime.ts';
import { getMapProvider } from '@/lib/server_settings.ts';
import { getMapWebsite } from '@/lib/map/index.ts';
import { getLicense, getThirdPartyLicenses } from '@/lib/licenses.ts';
@@ -16,7 +17,7 @@ import { formatDisplayVersion, getClientDisplayVersion, getClientBuildTime } fro
import { clearBrowserCaches } from '@/lib/ui/common.ts';
export function useAboutPageBase() {
const { tt, formatUnixTimeToLongDateTime } = useI18n();
const { tt, formatDateTimeToLongDateTime } = useI18n();
const systemsStore = useSystemsStore();
const exchangeRatesStore = useExchangeRatesStore();
@@ -41,7 +42,8 @@ export function useAboutPageBase() {
return time;
}
return formatUnixTimeToLongDateTime(parseInt(time));
const buildDateTime = parseDateTimeFromUnixTime(parseInt(time));
return formatDateTimeToLongDateTime(buildDateTime);
});
const exchangeRatesData = computed<LatestExchangeRateResponse | undefined>(() => exchangeRatesStore.latestExchangeRates.data);
+8 -3
View File
@@ -12,9 +12,10 @@ import type {
} from '@/models/exchange_rate.ts';
import { getExchangedAmountByRate } from '@/lib/numeral.ts';
import { parseDateTimeFromUnixTime } from '@/lib/datetime.ts';
export function useExchangeRatesPageBase() {
const { getAllDisplayExchangeRates, formatUnixTimeToLongDate, parseAmountFromWesternArabicNumerals } = useI18n();
const { getAllDisplayExchangeRates, formatDateTimeToLongDate, parseAmountFromWesternArabicNumerals } = useI18n();
const userStore = useUserStore();
const exchangeRatesStore = useExchangeRatesStore();
@@ -27,8 +28,12 @@ export function useExchangeRatesPageBase() {
const isUserCustomExchangeRates = computed<boolean>(() => exchangeRatesStore.isUserCustomExchangeRates);
const exchangeRatesDataUpdateTime = computed<string>(() => {
const exchangeRatesLastUpdateTime = exchangeRatesStore.exchangeRatesLastUpdateTime;
return exchangeRatesLastUpdateTime ? formatUnixTimeToLongDate(exchangeRatesLastUpdateTime) : '';
if (!exchangeRatesStore.exchangeRatesLastUpdateTime) {
return '';
}
const exchangeRatesLastUpdateTime = parseDateTimeFromUnixTime(exchangeRatesStore.exchangeRatesLastUpdateTime);
return formatDateTimeToLongDate(exchangeRatesLastUpdateTime);
});
const availableExchangeRates = computed<LocalizedLatestExchangeRate[]>(() => {
+13 -11
View File
@@ -17,12 +17,14 @@ import type {
TransactionOverviewResponseItem
} from '@/models/transaction.ts';
import { parseDateTimeFromUnixTime } from '@/lib/datetime.ts';
export function useHomePageBase() {
const {
formatUnixTimeToLongDate,
formatUnixTimeToLongMonthDay,
formatUnixTimeToGregorianLikeLongYear,
formatUnixTimeToGregorianLikeLongMonth,
formatDateTimeToLongDate,
formatDateTimeToLongMonthDay,
formatDateTimeToGregorianLikeLongYear,
formatDateTimeToGregorianLikeLongMonth,
formatAmountToLocalizedNumeralsWithCurrency
} = useI18n();
@@ -57,19 +59,19 @@ export function useHomePageBase() {
const displayDateRange = computed<TransactionOverviewDisplayTime>(() => {
return {
today: {
displayTime: formatUnixTimeToLongDate(overviewStore.transactionDataRange.today.startTime),
displayTime: formatDateTimeToLongDate(parseDateTimeFromUnixTime(overviewStore.transactionDataRange.today.startTime)),
},
thisWeek: {
startTime: formatUnixTimeToLongMonthDay(overviewStore.transactionDataRange.thisWeek.startTime),
endTime: formatUnixTimeToLongMonthDay(overviewStore.transactionDataRange.thisWeek.endTime)
startTime: formatDateTimeToLongMonthDay(parseDateTimeFromUnixTime(overviewStore.transactionDataRange.thisWeek.startTime)),
endTime: formatDateTimeToLongMonthDay(parseDateTimeFromUnixTime(overviewStore.transactionDataRange.thisWeek.endTime))
},
thisMonth: {
displayTime: formatUnixTimeToGregorianLikeLongMonth(overviewStore.transactionDataRange.thisMonth.startTime),
startTime: formatUnixTimeToLongMonthDay(overviewStore.transactionDataRange.thisMonth.startTime),
endTime: formatUnixTimeToLongMonthDay(overviewStore.transactionDataRange.thisMonth.endTime)
displayTime: formatDateTimeToGregorianLikeLongMonth(parseDateTimeFromUnixTime(overviewStore.transactionDataRange.thisMonth.startTime)),
startTime: formatDateTimeToLongMonthDay(parseDateTimeFromUnixTime(overviewStore.transactionDataRange.thisMonth.startTime)),
endTime: formatDateTimeToLongMonthDay(parseDateTimeFromUnixTime(overviewStore.transactionDataRange.thisMonth.endTime))
},
thisYear: {
displayTime: formatUnixTimeToGregorianLikeLongYear(overviewStore.transactionDataRange.thisYear.startTime)
displayTime: formatDateTimeToGregorianLikeLongYear(parseDateTimeFromUnixTime(overviewStore.transactionDataRange.thisYear.startTime))
}
};
});
+42 -4
View File
@@ -9,7 +9,13 @@ import { AccountCategory, AccountType } from '@/core/account.ts';
import type { LocalizedAccountCategory } from '@/core/account.ts';
import { Account } from '@/models/account.ts';
import { getCurrentUnixTime } from '@/lib/datetime.ts';
import { isDefined } from '@/lib/common.ts';
import {
getTimezoneOffsetMinutes,
getSameDateTimeWithCurrentTimezone,
parseDateTimeFromUnixTimeWithBrowserTimezone,
getCurrentUnixTime
} from '@/lib/datetime.ts';
export interface DayAndDisplayName {
readonly day: number;
@@ -25,7 +31,7 @@ export function useAccountEditPageBase() {
const clientSessionId = ref<string>('');
const loading = ref<boolean>(false);
const submitting = ref<boolean>(false);
const account = ref<Account>(Account.createNewAccount(userStore.currentUserDefaultCurrency, getCurrentUnixTime()));
const account = ref<Account>(Account.createNewAccount(userStore.currentUserDefaultCurrency, getCurrentUnixTimeForNewAccount()));
const subAccounts = ref<Account[]>([]);
const title = computed<string>(() => {
@@ -89,6 +95,18 @@ export function useAccountEditPageBase() {
const isAccountSupportCreditCardStatementDate = computed<boolean>(() => account.value && account.value.category === AccountCategory.CreditCard.type);
function getCurrentUnixTimeForNewAccount(): number {
return getSameDateTimeWithCurrentTimezone(parseDateTimeFromUnixTimeWithBrowserTimezone(getCurrentUnixTime())).getUnixTime();
}
function getDefaultTimezoneOffsetMinutes(account: Account): number {
if (!account.balanceTime) {
return 0;
}
return getTimezoneOffsetMinutes(account.balanceTime);
}
function getAccountCreditCardStatementDate(statementDate?: number): string | null {
for (const item of allAvailableMonthDays.value) {
if (item.day === statementDate) {
@@ -99,6 +117,23 @@ export function useAccountEditPageBase() {
return null;
}
function updateAccountBalanceTime(account: Account, balanceTime: number): void {
if (!isDefined(account.balanceTime)) {
account.balanceTime = balanceTime;
return;
}
const oldUtcOffset = getTimezoneOffsetMinutes(account.balanceTime);
const newUtcOffset = getTimezoneOffsetMinutes(balanceTime);
if (oldUtcOffset === newUtcOffset) {
account.balanceTime = balanceTime;
return;
}
account.balanceTime = balanceTime - (newUtcOffset - oldUtcOffset) * 60;
}
function getInputEmptyProblemMessage(account: Account, isSubAccount: boolean): string | null {
if (!isSubAccount && !account.category) {
return 'Account category cannot be blank';
@@ -122,7 +157,7 @@ export function useAccountEditPageBase() {
return false;
}
const subAccount = account.value.createNewSubAccount(userStore.currentUserDefaultCurrency, getCurrentUnixTime());
const subAccount = account.value.createNewSubAccount(userStore.currentUserDefaultCurrency, getCurrentUnixTimeForNewAccount());
subAccounts.value.push(subAccount);
return true;
}
@@ -133,7 +168,7 @@ export function useAccountEditPageBase() {
if (newAccount.subAccounts && newAccount.subAccounts.length > 0) {
for (const oldSubAccount of newAccount.subAccounts) {
const subAccount: Account = account.value.createNewSubAccount(userStore.currentUserDefaultCurrency, getCurrentUnixTime());
const subAccount: Account = account.value.createNewSubAccount(userStore.currentUserDefaultCurrency, getCurrentUnixTimeForNewAccount());
subAccount.fillFrom(oldSubAccount);
subAccounts.value.push(subAccount);
@@ -163,7 +198,10 @@ export function useAccountEditPageBase() {
allAvailableMonthDays,
isAccountSupportCreditCardStatementDate,
// functions
getCurrentUnixTimeForNewAccount,
getDefaultTimezoneOffsetMinutes,
getAccountCreditCardStatementDate,
updateAccountBalanceTime,
isNewAccount,
addSubAccount,
setAccount
@@ -2,7 +2,6 @@ import { ref, computed } from 'vue';
import { useI18n } from '@/locales/helpers.ts';
import { useSettingsStore } from '@/stores/setting.ts';
import { useUserStore } from '@/stores/user.ts';
import { useAccountsStore } from '@/stores/account.ts';
import { useTransactionCategoriesStore } from '@/stores/transactionCategory.ts';
@@ -25,7 +24,8 @@ import { replaceAll } from '@/lib/common.ts';
import {
getUtcOffsetByUtcOffsetMinutes,
getTimezoneOffsetMinutes,
parseDateTimeFromUnixTime
parseDateTimeFromUnixTime,
parseDateTimeFromUnixTimeWithTimezoneOffset
} from '@/lib/datetime.ts';
export function useReconciliationStatementPageBase() {
@@ -33,15 +33,14 @@ export function useReconciliationStatementPageBase() {
tt,
getAllAccountBalanceTrendChartTypes,
getAllStatisticsDateAggregationTypesWithShortName,
formatUnixTimeToLongDateTime,
formatUnixTimeToLongDate,
formatUnixTimeToShortTime,
formatUnixTimeToGregorianDefaultDateTime,
formatDateTimeToLongDateTime,
formatDateTimeToLongDate,
formatDateTimeToShortTime,
formatDateTimeToGregorianDefaultDateTime,
formatAmountToWesternArabicNumeralsWithoutDigitGrouping,
formatAmountToLocalizedNumeralsWithCurrency
} = useI18n();
const settingsStore = useSettingsStore();
const userStore = useUserStore();
const accountsStore = useAccountsStore();
const transactionCategoriesStore = useTransactionCategoriesStore();
@@ -53,7 +52,6 @@ export function useReconciliationStatementPageBase() {
const firstDayOfWeek = computed<WeekDayValue>(() => userStore.currentUserFirstDayOfWeek);
const fiscalYearStart = computed<number>(() => userStore.currentUserFiscalYearStart);
const currentTimezoneOffsetMinutes = computed<number>(() => getTimezoneOffsetMinutes(settingsStore.appSettings.timeZone));
const defaultCurrency = computed<string>(() => userStore.currentUserDefaultCurrency);
const allChartTypes = computed<TypeAndDisplayName[]>(() => getAllAccountBalanceTrendChartTypes());
@@ -79,11 +77,13 @@ export function useReconciliationStatementPageBase() {
const allCategoriesMap = computed<Record<string, TransactionCategory>>(() => transactionCategoriesStore.allTransactionCategoriesMap);
const displayStartDateTime = computed<string>(() => {
return formatUnixTimeToLongDateTime(startTime.value);
const dateTime = parseDateTimeFromUnixTime(startTime.value);
return formatDateTimeToLongDateTime(dateTime);
});
const displayEndDateTime = computed<string>(() => {
return formatUnixTimeToLongDateTime(endTime.value);
const dateTime = parseDateTimeFromUnixTime(endTime.value);
return formatDateTimeToLongDateTime(dateTime);
});
const displayTotalInflows = computed<string>(() => {
@@ -160,15 +160,22 @@ export function useReconciliationStatementPageBase() {
}
function getDisplayDateTime(transaction: TransactionReconciliationStatementResponseItemWithInfo): string {
return formatUnixTimeToLongDateTime(transaction.time, transaction.utcOffset, currentTimezoneOffsetMinutes.value);
const dateTime = parseDateTimeFromUnixTimeWithTimezoneOffset(transaction.time, transaction.utcOffset);
return formatDateTimeToLongDateTime(dateTime);
}
function getDisplayDate(transaction: TransactionReconciliationStatementResponseItemWithInfo): string {
return formatUnixTimeToLongDate(transaction.time, transaction.utcOffset, currentTimezoneOffsetMinutes.value);
const dateTime = parseDateTimeFromUnixTimeWithTimezoneOffset(transaction.time, transaction.utcOffset);
return formatDateTimeToLongDate(dateTime);
}
function getDisplayTime(transaction: TransactionReconciliationStatementResponseItemWithInfo): string {
return formatUnixTimeToShortTime(transaction.time, transaction.utcOffset, currentTimezoneOffsetMinutes.value);
const dateTime = parseDateTimeFromUnixTimeWithTimezoneOffset(transaction.time, transaction.utcOffset);
return formatDateTimeToShortTime(dateTime);
}
function isSameAsDefaultTimezoneOffsetMinutes(transaction: TransactionReconciliationStatementResponseItemWithInfo): boolean {
return transaction.utcOffset === getTimezoneOffsetMinutes(transaction.time);
}
function getDisplayTimezone(transaction: TransactionReconciliationStatementResponseItemWithInfo): string {
@@ -227,7 +234,7 @@ export function useReconciliationStatementPageBase() {
const transactions = reconciliationStatements.value?.transactions ?? [];
const rows = transactions.map(transaction => {
const transactionTime = parseDateTimeFromUnixTime(transaction.time, transaction.utcOffset, currentTimezoneOffsetMinutes.value).getUnixTime();
const transactionTime = parseDateTimeFromUnixTimeWithTimezoneOffset(transaction.time, transaction.utcOffset);
const type = getDisplayTransactionType(transaction);
let categoryName = transaction.categoryName;
let displayAmount = formatAmountToWesternArabicNumeralsWithoutDigitGrouping(transaction.sourceAmount);
@@ -260,7 +267,7 @@ export function useReconciliationStatementPageBase() {
}
return [
formatUnixTimeToGregorianDefaultDateTime(transactionTime),
formatDateTimeToGregorianDefaultDateTime(transactionTime),
type,
categoryName,
displayAmount,
@@ -282,7 +289,6 @@ export function useReconciliationStatementPageBase() {
// computed states
firstDayOfWeek,
fiscalYearStart,
currentTimezoneOffsetMinutes,
defaultCurrency,
allChartTypes,
allDateAggregationTypes,
@@ -303,6 +309,7 @@ export function useReconciliationStatementPageBase() {
getDisplayDateTime,
getDisplayDate,
getDisplayTime,
isSameAsDefaultTimezoneOffsetMinutes,
getDisplayTimezone,
getDisplaySourceAmount,
getDisplayDestinationAmount,
@@ -15,6 +15,7 @@ import { CategoryType } from '@/core/category.ts';
import type { Account } from '@/models/account.ts';
import { isObjectEmpty } from '@/lib/common.ts';
import { getCurrentUnixTime } from '@/lib/datetime.ts';
export function useAppSettingPageBase() {
const { tt, getAllTimezones, getAllTimezoneTypesUsedForStatistics, getAllCurrencySortingTypes, setTimeZone } = useI18n();
@@ -37,7 +38,7 @@ export function useAppSettingPageBase() {
];
});
const allTimezones = computed<LocalizedTimezoneInfo[]>(() => getAllTimezones(true));
const allTimezones = computed<LocalizedTimezoneInfo[]>(() => getAllTimezones(getCurrentUnixTime(), true));
const allTimezoneTypesUsedForStatistics = computed<TypeAndDisplayName[]>(() => getAllTimezoneTypesUsedForStatistics());
const allCurrencySortingTypes = computed<TypeAndDisplayName[]>(() => getAllCurrencySortingTypes());
@@ -28,7 +28,11 @@ import type {
} from '@/models/transaction.ts';
import { limitText, findNameByType, findDisplayNameByType } from '@/lib/common.ts';
import { getYearMonthFirstUnixTime, getYearMonthLastUnixTime } from '@/lib/datetime.ts';
import {
parseDateTimeFromUnixTime,
getYearMonthFirstUnixTime,
getYearMonthLastUnixTime
} from '@/lib/datetime.ts';
import { getDisplayColor, getCategoryDisplayColor, getAccountDisplayColor } from '@/lib/color.ts';
export function useStatisticsTransactionPageBase() {
@@ -37,8 +41,8 @@ export function useStatisticsTransactionPageBase() {
getAllDateRanges,
getAllStatisticsSortingTypes,
getAllStatisticsDateAggregationTypes,
formatUnixTimeToLongDateTime,
formatUnixTimeToGregorianLikeLongYearMonth,
formatDateTimeToLongDateTime,
formatDateTimeToGregorianLikeLongYearMonth,
formatDateRange,
formatAmountToLocalizedNumeralsWithCurrency
} = useI18n();
@@ -88,11 +92,11 @@ export function useStatisticsTransactionPageBase() {
const queryStartTime = computed<string>(() => {
if (analysisType.value === StatisticsAnalysisType.CategoricalAnalysis) {
return formatUnixTimeToLongDateTime(query.value.categoricalChartStartTime);
return formatDateTimeToLongDateTime(parseDateTimeFromUnixTime(query.value.categoricalChartStartTime));
} else if (analysisType.value === StatisticsAnalysisType.TrendAnalysis) {
return formatUnixTimeToGregorianLikeLongYearMonth(getYearMonthFirstUnixTime(query.value.trendChartStartYearMonth));
return formatDateTimeToGregorianLikeLongYearMonth(parseDateTimeFromUnixTime(getYearMonthFirstUnixTime(query.value.trendChartStartYearMonth)));
} else if (analysisType.value === StatisticsAnalysisType.AssetTrends) {
return formatUnixTimeToLongDateTime(query.value.assetTrendsChartStartTime);
return formatDateTimeToLongDateTime(parseDateTimeFromUnixTime(query.value.assetTrendsChartStartTime));
} else {
return '';
}
@@ -100,11 +104,11 @@ export function useStatisticsTransactionPageBase() {
const queryEndTime = computed<string>(() => {
if (analysisType.value === StatisticsAnalysisType.CategoricalAnalysis) {
return formatUnixTimeToLongDateTime(query.value.categoricalChartEndTime);
return formatDateTimeToLongDateTime(parseDateTimeFromUnixTime(query.value.categoricalChartEndTime));
} else if (analysisType.value === StatisticsAnalysisType.TrendAnalysis) {
return formatUnixTimeToGregorianLikeLongYearMonth(getYearMonthLastUnixTime(query.value.trendChartEndYearMonth));
return formatDateTimeToGregorianLikeLongYearMonth(parseDateTimeFromUnixTime(getYearMonthLastUnixTime(query.value.trendChartEndYearMonth)));
} else if (analysisType.value === StatisticsAnalysisType.AssetTrends) {
return formatUnixTimeToLongDateTime(query.value.assetTrendsChartEndTime);
return formatDateTimeToLongDateTime(parseDateTimeFromUnixTime(query.value.assetTrendsChartEndTime));
} else {
return '';
}
@@ -36,6 +36,8 @@ import {
import {
getUtcOffsetByUtcOffsetMinutes,
getTimezoneOffsetMinutes,
getSameDateTimeWithCurrentTimezone,
parseDateTimeFromUnixTimeWithBrowserTimezone,
getCurrentUnixTime
} from '@/lib/datetime.ts';
@@ -92,14 +94,14 @@ export function useTransactionEditPageBase(type: TransactionEditPageType, initMo
const transaction = ref<Transaction | TransactionTemplate>(createNewTransactionModel(transactionDefaultType));
const numeralSystem = computed<NumeralSystem>(() => getCurrentNumeralSystemType());
const currentTimezoneOffsetMinutes = computed<number>(() => getTimezoneOffsetMinutes(settingsStore.appSettings.timeZone));
const currentTimezoneOffsetMinutes = computed<number>(() => getTimezoneOffsetMinutes(transaction.value.time));
const showAccountBalance = computed<boolean>(() => settingsStore.appSettings.showAccountBalance);
const defaultCurrency = computed<string>(() => userStore.currentUserDefaultCurrency);
const defaultAccountId = computed<string>(() => userStore.currentUserDefaultAccountId);
const firstDayOfWeek = computed<WeekDayValue>(() => userStore.currentUserFirstDayOfWeek);
const coordinateDisplayType = computed<number>(() => userStore.currentUserCoordinateDisplayType);
const allTimezones = computed<LocalizedTimezoneInfo[]>(() => getAllTimezones(true));
const allTimezones = computed<LocalizedTimezoneInfo[]>(() => getAllTimezones(transaction.value.time, true));
const allAccounts = computed<Account[]>(() => accountsStore.allPlainAccounts);
const allVisibleAccounts = computed<Account[]>(() => accountsStore.allVisiblePlainAccounts);
const allAccountsMap = computed<Record<string, Account>>(() => accountsStore.allAccountsMap);
@@ -274,7 +276,7 @@ export function useTransactionEditPageBase(type: TransactionEditPageType, initMo
});
const transactionTimezoneTimeDifference = computed<string>(() => {
return getTimezoneDifferenceDisplayText(transaction.value.utcOffset);
return getTimezoneDifferenceDisplayText(transaction.value.time, transaction.value.utcOffset);
});
const geoLocationStatusInfo = computed<string>(() => {
@@ -331,8 +333,12 @@ export function useTransactionEditPageBase(type: TransactionEditPageType, initMo
return !!inputEmptyProblemMessage.value;
});
function getCurrentUnixTimeForNewTransaction(): number {
return getSameDateTimeWithCurrentTimezone(parseDateTimeFromUnixTimeWithBrowserTimezone(getCurrentUnixTime())).getUnixTime();
}
function createNewTransactionModel(transactionType?: number): Transaction | TransactionTemplate {
const now: number = getCurrentUnixTime();
const now: number = getCurrentUnixTimeForNewTransaction();
const currentTimezone: string = settingsStore.appSettings.timeZone;
let defaultType: TransactionType = TransactionType.Expense;
@@ -343,7 +349,7 @@ export function useTransactionEditPageBase(type: TransactionEditPageType, initMo
defaultType = TransactionType.Transfer;
}
let newTransaction: Transaction | TransactionTemplate = Transaction.createNewTransaction(defaultType, now, currentTimezone, getTimezoneOffsetMinutes(currentTimezone));
let newTransaction: Transaction | TransactionTemplate = Transaction.createNewTransaction(defaultType, now, currentTimezone, getTimezoneOffsetMinutes(now, currentTimezone));
if (type === TransactionEditPageType.Template) {
newTransaction = TransactionTemplate.createNewTransactionTemplate(newTransaction);
@@ -352,6 +358,25 @@ export function useTransactionEditPageBase(type: TransactionEditPageType, initMo
return newTransaction;
}
function updateTransactionTime(newTime: number): void {
transaction.value.time = newTime;
updateTransactionTimezone(transaction.value.timeZone ?? '');
}
function updateTransactionTimezone(timezoneName: string): void {
const oldUtcOffset = transaction.value.utcOffset;
for (const timezone of allTimezones.value) {
if (timezone.name === timezoneName) {
transaction.value.timeZone = timezone.name;
transaction.value.utcOffset = timezone.utcOffsetMinutes;
break;
}
}
transaction.value.time = transaction.value.time - (transaction.value.utcOffset - oldUtcOffset) * 60;
}
function swapTransactionData(swapAccount: boolean, swapAmount: boolean): void {
if (swapAccount) {
const oldSourceAccountId = transaction.value.sourceAccountId;
@@ -396,15 +421,6 @@ export function useTransactionEditPageBase(type: TransactionEditPageType, initMo
}
});
watch(() => transaction.value.timeZone, (newValue) => {
for (const timezone of allTimezones.value) {
if (timezone.name === newValue) {
transaction.value.utcOffset = timezone.utcOffsetMinutes;
break;
}
}
});
return {
// constants
isSupportGeoLocation,
@@ -460,6 +476,8 @@ export function useTransactionEditPageBase(type: TransactionEditPageType, initMo
inputIsEmpty,
// functions
createNewTransactionModel,
updateTransactionTime,
updateTransactionTimezone,
swapTransactionData,
getDisplayAmount,
getTransactionPictureUrl
@@ -23,13 +23,12 @@ import { type Transaction, TransactionTagFilter } from '@/models/transaction.ts'
import {
getUtcOffsetByUtcOffsetMinutes,
getTimezoneOffset,
getTimezoneOffsetMinutes,
getBrowserTimezoneOffsetMinutes,
getLocalDatetimeFromUnixTime,
getDummyUnixTimeForLocalUsage,
getSameDateTimeWithBrowserTimezone,
getCurrentDateTime,
parseDateTimeFromUnixTime,
parseDateTimeFromUnixTimeWithTimezoneOffset,
getYearMonthFirstUnixTime,
isDateRangeMatchOneMonth
} from '@/lib/datetime.ts';
@@ -76,10 +75,10 @@ export function useTransactionListPageBase() {
tt,
getAllDateRanges,
getCurrentNumeralSystemType,
formatUnixTimeToLongDateTime,
formatUnixTimeToLongDate,
formatUnixTimeToShortTime,
formatUnixTimeToGregorianLikeLongYearMonth,
formatDateTimeToLongDateTime,
formatDateTimeToLongDate,
formatDateTimeToShortTime,
formatDateTimeToGregorianLikeLongYearMonth,
formatDateRange,
formatAmountToLocalizedNumeralsWithCurrency
} = useI18n();
@@ -98,7 +97,6 @@ export function useTransactionListPageBase() {
const currentCalendarDate = ref<TextualYearMonthDay | ''>('');
const numeralSystem = computed<NumeralSystem>(() => getCurrentNumeralSystemType());
const currentTimezoneOffsetMinutes = computed<number>(() => getTimezoneOffsetMinutes(settingsStore.appSettings.timeZone));
const firstDayOfWeek = computed<WeekDayValue>(() => userStore.currentUserFirstDayOfWeek);
const fiscalYearStart = computed<number>(() => userStore.currentUserFiscalYearStart);
const defaultCurrency = computed<string>(() => getUnifiedSelectedAccountsCurrencyOrDefaultCurrency(allAccountsMap.value, queryAllFilterAccountIds.value, userStore.currentUserDefaultCurrency));
@@ -161,8 +159,8 @@ export function useTransactionListPageBase() {
return formatDateRange(query.value.dateType, query.value.minTime, query.value.maxTime);
});
const queryMinTime = computed<string>(() => formatUnixTimeToLongDateTime(query.value.minTime));
const queryMaxTime = computed<string>(() => formatUnixTimeToLongDateTime(query.value.maxTime));
const queryMinTime = computed<string>(() => formatDateTimeToLongDateTime(parseDateTimeFromUnixTime(query.value.minTime)));
const queryMaxTime = computed<string>(() => formatDateTimeToLongDateTime(parseDateTimeFromUnixTime(query.value.maxTime)));
const queryMonthlyData = computed<boolean>(() => isDateRangeMatchOneMonth(query.value.minTime, query.value.maxTime));
const queryMonth = computed<Year0BasedMonth>(() => {
if (!query.value.minTime || !query.value.maxTime) {
@@ -235,8 +233,8 @@ export function useTransactionListPageBase() {
return displayAmount.join(' ~ ');
});
const transactionCalendarMinDate = computed<Date>(() => getLocalDatetimeFromUnixTime(getDummyUnixTimeForLocalUsage(query.value.minTime, getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes())));
const transactionCalendarMaxDate = computed<Date>(() => getLocalDatetimeFromUnixTime(getDummyUnixTimeForLocalUsage(query.value.maxTime, getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes())));
const transactionCalendarMinDate = computed<Date>(() => getLocalDatetimeFromUnixTime(getSameDateTimeWithBrowserTimezone(parseDateTimeFromUnixTime(query.value.minTime)).getUnixTime()));
const transactionCalendarMaxDate = computed<Date>(() => getLocalDatetimeFromUnixTime(getSameDateTimeWithBrowserTimezone(parseDateTimeFromUnixTime(query.value.maxTime)).getUnixTime()));
const currentMonthTransactionData = computed<TransactionMonthList | null>(() => {
const allTransactions = transactionsStore.transactions;
@@ -284,6 +282,10 @@ export function useTransactionListPageBase() {
return false;
}
function isSameAsDefaultTimezoneOffsetMinutes(transaction: Transaction): boolean {
return transaction.utcOffset === getTimezoneOffsetMinutes(transaction.time);
}
function formatAmount(amount: number, hideAmount: boolean, currencyCode: string): string {
if (hideAmount) {
return formatAmountToLocalizedNumeralsWithCurrency(DISPLAY_HIDDEN_AMOUNT, currencyCode);
@@ -293,15 +295,18 @@ export function useTransactionListPageBase() {
}
function getDisplayTime(transaction: Transaction): string {
return formatUnixTimeToShortTime(transaction.time, transaction.utcOffset, currentTimezoneOffsetMinutes.value);
const dateTime = parseDateTimeFromUnixTimeWithTimezoneOffset(transaction.time, transaction.utcOffset);
return formatDateTimeToShortTime(dateTime);
}
function getDisplayLongDate(transaction: Transaction): string {
return formatUnixTimeToLongDate(transaction.time, transaction.utcOffset, currentTimezoneOffsetMinutes.value);
const dateTime = parseDateTimeFromUnixTimeWithTimezoneOffset(transaction.time, transaction.utcOffset);
return formatDateTimeToLongDate(dateTime);
}
function getDisplayLongYearMonth(transactionMonthList: TransactionMonthList): string {
return formatUnixTimeToGregorianLikeLongYearMonth(getYearMonthFirstUnixTime(transactionMonthList.yearDashMonth));
const yearMonthDateTime = parseDateTimeFromUnixTime(getYearMonthFirstUnixTime(transactionMonthList.yearDashMonth));
return formatDateTimeToGregorianLikeLongYearMonth(yearMonthDateTime);
}
function getDisplayTimezone(transaction: Transaction): string {
@@ -310,8 +315,10 @@ export function useTransactionListPageBase() {
}
function getDisplayTimeInDefaultTimezone(transaction: Transaction): string {
const utcOffset = numeralSystem.value.replaceWesternArabicDigitsToLocalizedDigits(getTimezoneOffset(settingsStore.appSettings.timeZone));
return `${formatUnixTimeToLongDateTime(transaction.time)} (UTC${utcOffset})`;
const timezoneOffsetMinutes = getTimezoneOffsetMinutes(transaction.time);
const dateTime = parseDateTimeFromUnixTimeWithTimezoneOffset(transaction.time, timezoneOffsetMinutes);
const utcOffset = numeralSystem.value.replaceWesternArabicDigitsToLocalizedDigits(getUtcOffsetByUtcOffsetMinutes(timezoneOffsetMinutes));
return `${formatDateTimeToLongDateTime(dateTime)} (UTC${utcOffset})`;
}
function getDisplayAmount(transaction: Transaction): string {
@@ -372,7 +379,6 @@ export function useTransactionListPageBase() {
customMaxDatetime,
currentCalendarDate,
// computed states
currentTimezoneOffsetMinutes,
firstDayOfWeek,
fiscalYearStart,
defaultCurrency,
@@ -410,6 +416,7 @@ export function useTransactionListPageBase() {
canAddTransaction,
// functions
hasSubCategoryInQuery,
isSameAsDefaultTimezoneOffsetMinutes,
getDisplayTime,
getDisplayLongDate,
getDisplayLongYearMonth,
+1 -5
View File
@@ -202,12 +202,10 @@ import { useAccountsStore } from '@/stores/account.ts';
import { useTransactionCategoriesStore } from '@/stores/transactionCategory.ts';
import { useOverviewStore } from '@/stores/overview.ts';
import { entries } from '@/core/base.ts';
import { type NumeralSystem } from '@/core/numeral.ts';
import { DateRange } from '@/core/datetime.ts';
import { ThemeType } from '@/core/theme.ts';
import {
type TransactionAmountsRequestType,
type TransactionMonthlyIncomeAndExpenseData,
LATEST_12MONTHS_TRANSACTION_AMOUNTS_REQUEST_TYPES
} from '@/models/transaction.ts';
@@ -280,8 +278,7 @@ const monthlyIncomeAndExpenseData = computed<TransactionMonthlyIncomeAndExpenseD
return data;
}
for (const [type, monthDiff] of entries(LATEST_12MONTHS_TRANSACTION_AMOUNTS_REQUEST_TYPES)) {
const amountRequestType = type as TransactionAmountsRequestType;
for (const amountRequestType of LATEST_12MONTHS_TRANSACTION_AMOUNTS_REQUEST_TYPES) {
const dateRange = overviewStore.transactionDataRange[amountRequestType];
if (!dateRange) {
@@ -292,7 +289,6 @@ const monthlyIncomeAndExpenseData = computed<TransactionMonthlyIncomeAndExpenseD
data.push({
monthStartTime: dateRange.startTime,
monthsBeforeCurrentMonth: monthDiff,
incomeAmount: item?.incomeAmount || 0,
expenseAmount: item?.expenseAmount || 0,
incompleteIncomeAmount: item ? item.incompleteIncomeAmount : true,
@@ -145,7 +145,9 @@
<date-time-select
:disabled="loading || submitting"
:label="tt('Balance Time')"
v-model="selectedAccount.balanceTime"
:timezone-utc-offset="getDefaultTimezoneOffsetMinutes(selectedAccount)"
:model-value="selectedAccount.balanceTime"
@update:model-value="updateAccountBalanceTime(selectedAccount, $event)"
@error="onShowDateTimeError" />
</v-col>
<v-col cols="12" md="12">
@@ -210,7 +212,6 @@ import { ALL_ACCOUNT_COLORS } from '@/consts/color.ts';
import { Account } from '@/models/account.ts';
import { isNumber } from '@/lib/common.ts';
import { getCurrentUnixTime } from '@/lib/datetime.ts';
import { generateRandomUUID } from '@/lib/misc.ts';
import {
@@ -242,6 +243,9 @@ const {
allAccountTypes,
allAvailableMonthDays,
isAccountSupportCreditCardStatementDate,
getCurrentUnixTimeForNewAccount,
getDefaultTimezoneOffsetMinutes,
updateAccountBalanceTime,
isNewAccount,
addSubAccount,
setAccount
@@ -275,7 +279,7 @@ const accountAmountTitle = computed<string>(() => {
const isAccountModified = computed<boolean>(() => {
if (!editAccountId.value) {
return !account.value.equals(Account.createNewAccount(userStore.currentUserDefaultCurrency, account.value.balanceTime ?? getCurrentUnixTime()));
return !account.value.equals(Account.createNewAccount(userStore.currentUserDefaultCurrency, account.value.balanceTime ?? getCurrentUnixTimeForNewAccount()));
} else {
return true;
}
@@ -289,7 +293,7 @@ function open(options?: { id?: string, currentAccount?: Account, category?: numb
loading.value = true;
submitting.value = false;
const newAccount = Account.createNewAccount(userStore.currentUserDefaultCurrency, getCurrentUnixTime());
const newAccount = Account.createNewAccount(userStore.currentUserDefaultCurrency, getCurrentUnixTimeForNewAccount());
account.value.fillFrom(newAccount);
subAccounts.value = [];
currentAccountIndex.value = -1;
@@ -149,7 +149,7 @@
<template #item.time="{ item }">
<span>{{ getDisplayDateTime(item) }}</span>
<v-chip class="ms-1" variant="flat" color="secondary" size="x-small"
v-if="item.utcOffset !== currentTimezoneOffsetMinutes">{{ getDisplayTimezone(item) }}</v-chip>
v-if="!isSameAsDefaultTimezoneOffsetMinutes(item)">{{ getDisplayTimezone(item) }}</v-chip>
</template>
<template #item.type="{ item }">
<v-chip label variant="outlined" size="x-small"
@@ -323,7 +323,6 @@ const {
startTime,
endTime,
reconciliationStatements,
currentTimezoneOffsetMinutes,
fiscalYearStart,
allChartTypes,
allDateAggregationTypes,
@@ -341,6 +340,7 @@ const {
setReconciliationStatements,
getDisplayTransactionType,
getDisplayDateTime,
isSameAsDefaultTimezoneOffsetMinutes,
getDisplayTimezone,
getDisplaySourceAmount,
getDisplayDestinationAmount,
+5 -4
View File
@@ -151,9 +151,10 @@ import {
} from '@/models/transaction.ts';
import {
parseDateTimeFromUnixTime,
getShiftedDateRangeAndDateType,
getDateTypeByDateRange,
getDateRangeByDateType,
getDateRangeByDateType
} from '@/lib/datetime.ts';
import {
@@ -188,7 +189,7 @@ const {
tt,
getAllDateRanges,
getCurrentNumeralSystemType,
formatUnixTimeToLongDateTime,
formatDateTimeToLongDateTime,
formatDateRange
} = useI18n();
@@ -221,8 +222,8 @@ const filteredTransactions = computed<TransactionInsightDataItem[]>(() => explor
const allDateRanges = computed<LocalizedDateRange[]>(() => getAllDateRanges(DateRangeScene.InsightsExplore, true));
const canShiftDateRange = computed<boolean>(() => query.value.dateRangeType !== DateRange.All.type);
const displayQueryDateRangeName = computed<string>(() => formatDateRange(query.value.dateRangeType, query.value.startTime, query.value.endTime));
const displayQueryStartTime = computed<string>(() => formatUnixTimeToLongDateTime(query.value.startTime));
const displayQueryEndTime = computed<string>(() => formatUnixTimeToLongDateTime(query.value.endTime));
const displayQueryStartTime = computed<string>(() => formatDateTimeToLongDateTime(parseDateTimeFromUnixTime(query.value.startTime)));
const displayQueryEndTime = computed<string>(() => formatDateTimeToLongDateTime(parseDateTimeFromUnixTime(query.value.endTime)));
const allTabs = computed<{ name: string, value: ExplorePageTabType }[]>(() => {
return [
@@ -14,7 +14,7 @@
<template #item.time="{ item }">
<span>{{ getDisplayDateTime(item) }}</span>
<v-chip class="ms-1" variant="flat" color="secondary" size="x-small"
v-if="item.utcOffset !== currentTimezoneOffsetMinutes">{{ getDisplayTimezone(item) }}</v-chip>
v-if="!isSameAsDefaultTimezoneOffsetMinutes(item)">{{ getDisplayTimezone(item) }}</v-chip>
</template>
<template #item.type="{ item }">
<v-chip label variant="outlined" size="x-small"
@@ -76,7 +76,6 @@ import { ref, computed } from 'vue';
import { useI18n } from '@/locales/helpers.ts';
import { useSettingsStore } from '@/stores/setting.ts';
import { useUserStore } from '@/stores/user.ts';
import { useExploresStore } from '@/stores/explore.ts';
@@ -89,7 +88,7 @@ import {
import {
getUtcOffsetByUtcOffsetMinutes,
getTimezoneOffsetMinutes,
parseDateTimeFromUnixTime
parseDateTimeFromUnixTimeWithTimezoneOffset
} from '@/lib/datetime.ts';
import {
@@ -109,19 +108,17 @@ const emit = defineEmits<{
const {
tt,
formatUnixTimeToLongDateTime,
formatUnixTimeToGregorianDefaultDateTime,
formatDateTimeToLongDateTime,
formatDateTimeToGregorianDefaultDateTime,
formatAmountToWesternArabicNumeralsWithoutDigitGrouping,
formatAmountToLocalizedNumeralsWithCurrency
} = useI18n();
const settingsStore = useSettingsStore();
const userStore = useUserStore();
const exploresStore = useExploresStore();
const currentPage = ref<number>(1);
const currentTimezoneOffsetMinutes = computed<number>(() => getTimezoneOffsetMinutes(settingsStore.appSettings.timeZone));
const defaultCurrency = computed<string>(() => userStore.currentUserDefaultCurrency);
const filteredTransactions = computed<TransactionInsightDataItem[]>(() => exploresStore.filteredTransactions);
@@ -163,7 +160,12 @@ const dataTableHeaders = computed<object[]>(() => {
});
function getDisplayDateTime(transaction: TransactionInsightDataItem): string {
return formatUnixTimeToLongDateTime(transaction.time, transaction.utcOffset, currentTimezoneOffsetMinutes.value);
const dateTime = parseDateTimeFromUnixTimeWithTimezoneOffset(transaction.time, transaction.utcOffset);
return formatDateTimeToLongDateTime(dateTime);
}
function isSameAsDefaultTimezoneOffsetMinutes(transaction: TransactionInsightDataItem): boolean {
return transaction.utcOffset === getTimezoneOffsetMinutes(transaction.time);
}
function getDisplayTimezone(transaction: TransactionInsightDataItem): string {
@@ -234,7 +236,7 @@ function buildExportResults(): { headers: string[], data: string[][] } | undefin
],
data: filteredTransactions.value
.map(transaction => {
const transactionTime = parseDateTimeFromUnixTime(transaction.time, transaction.utcOffset, currentTimezoneOffsetMinutes.value).getUnixTime();
const transactionTime = parseDateTimeFromUnixTimeWithTimezoneOffset(transaction.time, transaction.utcOffset);
const type = getDisplayTransactionType(transaction);
let categoryName = transaction.secondaryCategoryName;
@@ -254,7 +256,7 @@ function buildExportResults(): { headers: string[], data: string[][] } | undefin
const description = transaction.comment || '';
return [
formatUnixTimeToGregorianDefaultDateTime(transactionTime),
formatDateTimeToGregorianDefaultDateTime(transactionTime),
type,
categoryName,
displayAmount,
@@ -41,7 +41,7 @@ import { DISPLAY_HIDDEN_AMOUNT, INCOMPLETE_AMOUNT_SUFFIX } from '@/consts/numera
import { type TransactionMonthlyIncomeAndExpenseData } from '@/models/transaction.ts';
import { getUnixTimeBeforeUnixTime, getThisMonthFirstUnixTime } from '@/lib/datetime.ts';
import { parseDateTimeFromUnixTime } from '@/lib/datetime.ts';
import { getExpenseAndIncomeAmountColor } from '@/lib/ui/common.ts';
export interface MonthlyIncomeAndExpenseCardClickEvent {
@@ -64,7 +64,7 @@ const emit = defineEmits<{
const {
tt,
getCurrentLanguageTextDirection,
formatUnixTimeToGregorianLikeShortMonth,
formatDateTimeToGregorianLikeShortMonth,
formatAmountToLocalizedNumeralsWithCurrency
} = useI18n();
@@ -98,11 +98,9 @@ const chartOptions = computed<object>(() => {
const expenseIncomeAmountColor = getExpenseAndIncomeAmountColor(userStore.currentUserExpenseAmountColor, userStore.currentUserIncomeAmountColor, props.isDarkMode);
if (props.data) {
const currentMonthFirstUnixTime = getThisMonthFirstUnixTime();
for (const item of props.data) {
const monthFirstUnixTime = getUnixTimeBeforeUnixTime(currentMonthFirstUnixTime, item.monthsBeforeCurrentMonth, 'months');
const monthShortName = formatUnixTimeToGregorianLikeShortMonth(monthFirstUnixTime);
const monthStartDateTime = parseDateTimeFromUnixTime(item.monthStartTime);
const monthShortName = formatDateTimeToGregorianLikeShortMonth(monthStartDateTime);
monthNames.push(monthShortName);
incomeAmounts.push(item.incomeAmount);
+4 -6
View File
@@ -534,8 +534,8 @@
<td class="transaction-table-column-time">
<div class="d-flex flex-column">
<span>{{ getDisplayTime(transaction) }}</span>
<span class="text-caption" v-if="transaction.utcOffset !== currentTimezoneOffsetMinutes">{{ getDisplayTimezone(transaction) }}</span>
<v-tooltip activator="parent" v-if="transaction.utcOffset !== currentTimezoneOffsetMinutes">{{ getDisplayTimeInDefaultTimezone(transaction) }}</v-tooltip>
<span class="text-caption" v-if="!isSameAsDefaultTimezoneOffsetMinutes(transaction)">{{ getDisplayTimezone(transaction) }}</span>
<v-tooltip activator="parent" v-if="!isSameAsDefaultTimezoneOffsetMinutes(transaction)">{{ getDisplayTimeInDefaultTimezone(transaction) }}</v-tooltip>
</div>
</td>
<td class="transaction-table-column-category">
@@ -691,8 +691,6 @@ import {
import {
getCurrentUnixTime,
parseDateTimeFromUnixTime,
getBrowserTimezoneOffsetMinutes,
getActualUnixTimeForStore,
getDayFirstUnixTimeBySpecifiedUnixTime,
getYearMonthFirstUnixTime,
getYearMonthLastUnixTime,
@@ -775,7 +773,6 @@ const {
customMinDatetime,
customMaxDatetime,
currentCalendarDate,
currentTimezoneOffsetMinutes,
firstDayOfWeek,
fiscalYearStart,
defaultCurrency,
@@ -809,6 +806,7 @@ const {
transactionCalendarMaxDate,
currentMonthTransactionData,
hasSubCategoryInQuery,
isSameAsDefaultTimezoneOffsetMinutes,
canAddTransaction,
getDisplayTime,
getDisplayLongDate,
@@ -1234,7 +1232,7 @@ function changePageType(type: number): void {
function changeDateFilter(dateRange: TimeRangeAndDateType | number | null): void {
if (dateRange === DateRange.Custom.type || (isObject(dateRange) && dateRange.dateType === DateRange.Custom.type && !dateRange.minTime && !dateRange.maxTime)) { // Custom
if (!query.value.minTime || !query.value.maxTime) {
customMaxDatetime.value = getActualUnixTimeForStore(getCurrentUnixTime(), currentTimezoneOffsetMinutes.value, getBrowserTimezoneOffsetMinutes());
customMaxDatetime.value = getCurrentUnixTime();
customMinDatetime.value = getDayFirstUnixTimeBySpecifiedUnixTime(customMaxDatetime.value);
} else {
customMaxDatetime.value = query.value.maxTime;
@@ -81,7 +81,7 @@
<template #item.time="{ item }">
<span>{{ getDisplayDateTime(item) }}</span>
<v-chip class="ms-1" variant="flat" color="grey" size="x-small"
v-if="item.utcOffset !== currentTimezoneOffsetMinutes">{{ getDisplayTimezone(item) }}</v-chip>
v-if="!isSameAsDefaultTimezoneOffsetMinutes(item)">{{ getDisplayTimezone(item) }}</v-chip>
</template>
<template #item.type="{ value }">
<v-chip label color="secondary" variant="outlined" size="x-small" v-if="value === TransactionType.ModifyBalance">{{ tt('Modify Balance') }}</v-chip>
@@ -427,7 +427,9 @@ import {
} from '@/lib/common.ts';
import {
getUtcOffsetByUtcOffsetMinutes,
getTimezoneOffsetMinutes
getTimezoneOffsetMinutes,
parseDateTimeFromUnixTime,
parseDateTimeFromUnixTimeWithTimezoneOffset
} from '@/lib/datetime.ts';
import { formatCoordinate } from '@/lib/coordinate.ts';
import {
@@ -495,7 +497,7 @@ const props = defineProps<{
const {
tt,
getCurrentNumeralSystemType,
formatUnixTimeToLongDateTime,
formatDateTimeToLongDateTime,
formatAmountToLocalizedNumeralsWithCurrency,
getCategorizedAccountsWithDisplayBalance
} = useI18n();
@@ -536,7 +538,6 @@ const currentDescriptionFilterValue = ref<string | null>(null);
const numeralSystem = computed<NumeralSystem>(() => getCurrentNumeralSystemType());
const showAccountBalance = computed<boolean>(() => settingsStore.appSettings.showAccountBalance);
const currentTimezoneOffsetMinutes = computed<number>(() => getTimezoneOffsetMinutes(settingsStore.appSettings.timeZone));
const defaultCurrency = computed<string>(() => userStore.currentUserDefaultCurrency);
const coordinateDisplayType = computed<number>(() => userStore.currentUserCoordinateDisplayType);
@@ -1129,8 +1130,8 @@ const displayFilterCustomDateRange = computed<string>(() => {
return '';
}
const minDisplayTime = formatUnixTimeToLongDateTime(filters.value.minDatetime);
const maxDisplayTime = formatUnixTimeToLongDateTime(filters.value.maxDatetime);
const minDisplayTime = formatDateTimeToLongDateTime(parseDateTimeFromUnixTime(filters.value.minDatetime));
const maxDisplayTime = formatDateTimeToLongDateTime(parseDateTimeFromUnixTime(filters.value.maxDatetime));
return `${minDisplayTime} - ${maxDisplayTime}`
});
@@ -1272,7 +1273,12 @@ function isTagValid(tagIds: string[], tagIndex: number): boolean {
}
function getDisplayDateTime(transaction: ImportTransaction): string {
return formatUnixTimeToLongDateTime(transaction.time, transaction.utcOffset, currentTimezoneOffsetMinutes.value);
const dateTime = parseDateTimeFromUnixTimeWithTimezoneOffset(transaction.time, transaction.utcOffset)
return formatDateTimeToLongDateTime(dateTime);
}
function isSameAsDefaultTimezoneOffsetMinutes(transaction: ImportTransaction): boolean {
return transaction.utcOffset === getTimezoneOffsetMinutes(transaction.time);
}
function getDisplayTimezone(transaction: ImportTransaction): string {
@@ -54,7 +54,10 @@ import { KnownFileType } from '@/core/file.ts';
import type { ImportTransactionRequest, ImportTransactionRequestItem } from '@/models/imported_transaction.ts';
import { isDefined } from '@/lib/common.ts';
import { getBrowserTimezoneOffsetMinutes } from '@/lib/datetime.ts';
import {
getTimezoneOffsetMinutes,
getCurrentUnixTime
} from '@/lib/datetime.ts';
import {
openTextFileContent,
startDownloadFile
@@ -121,7 +124,7 @@ function parse(row, index) {
return {
time: row[0], // ${tt('sample.importTransactionCustomScript.fieldTimeDescription')}
utcOffset: '${getBrowserTimezoneOffsetMinutes()}', // ${tt('sample.importTransactionCustomScript.fieldUtcOffsetDescription')}
utcOffset: '${getTimezoneOffsetMinutes(getCurrentUnixTime())}', // ${tt('sample.importTransactionCustomScript.fieldUtcOffsetDescription')}
type: TransactionType.Expense, // ${tt('sample.importTransactionCustomScript.fieldTypeDescription')}
categoryName: row[4], // ${tt('sample.importTransactionCustomScript.fieldCategoryNameDescription')}
sourceAccountName: row[5], // ${tt('sample.importTransactionCustomScript.fieldSourceAccountNameDescription')}
@@ -250,7 +250,9 @@
:readonly="mode === TransactionEditPageMode.View"
:disabled="loading || submitting || (mode === TransactionEditPageMode.Edit && transaction.type === TransactionType.ModifyBalance)"
:label="tt('Transaction Time')"
v-model="transaction.time"
:timezone-utc-offset="transaction.utcOffset"
:model-value="transaction.time"
@update:model-value="updateTransactionTime"
@error="onShowDateTimeError" />
</v-col>
<v-col cols="12" md="6" v-if="type === TransactionEditPageType.Template && transaction instanceof TransactionTemplate && transaction.templateType === TemplateType.Schedule.type">
@@ -274,7 +276,8 @@
:placeholder="!transaction.timeZone && transaction.timeZone !== '' ? `(${transactionDisplayTimezone}) ${transactionTimezoneTimeDifference}` : tt('Timezone')"
:items="allTimezones"
:no-data-text="tt('No results')"
v-model="transaction.timeZone"
:model-value="transaction.timeZone"
@update:model-value="updateTransactionTimezone"
>
<template #selection="{ item }">
<span class="text-truncate" v-if="transaction.timeZone || transaction.timeZone === ''">
@@ -642,6 +645,8 @@ const {
inputEmptyProblemMessage,
inputIsEmpty,
createNewTransactionModel,
updateTransactionTime,
updateTransactionTimezone,
swapTransactionData,
getTransactionPictureUrl
} = useTransactionEditPageBase(props.type);
@@ -714,7 +719,7 @@ const isTransactionModified = computed<boolean>(() => {
}
});
function setTransaction(newTransaction: Transaction | null, options: SetTransactionOptions, setContextData: boolean, convertContextTime: boolean): void {
function setTransaction(newTransaction: Transaction | null, options: SetTransactionOptions, setContextData: boolean): void {
setTransactionModelByTransaction(
transaction.value,
newTransaction,
@@ -735,8 +740,7 @@ function setTransaction(newTransaction: Transaction | null, options: SetTransact
tagIds: options.tagIds,
comment: options.comment
},
setContextData,
convertContextTime
setContextData
);
}
@@ -758,7 +762,7 @@ function open(options: TransactionEditOptions): Promise<TransactionEditResponse
initTagIds.value = options.tagIds;
const newTransaction = createNewTransactionModel(options.type);
setTransaction(newTransaction, options, true, false);
setTransaction(newTransaction, options, true);
const promises: Promise<unknown>[] = [
accountsStore.loadAllAccounts({ force: false }),
@@ -769,7 +773,7 @@ function open(options: TransactionEditOptions): Promise<TransactionEditResponse
if (props.type === TransactionEditPageType.Transaction) {
if (options && options.id) {
if (options.currentTransaction) {
setTransaction(options.currentTransaction, options, true, true);
setTransaction(options.currentTransaction, options, true);
}
mode.value = TransactionEditPageMode.View;
@@ -781,10 +785,10 @@ function open(options: TransactionEditOptions): Promise<TransactionEditResponse
editId.value = null;
if (options.template) {
setTransaction(options.template, options, false, false);
setTransaction(options.template, options, false);
addByTemplateId.value = options.template.id;
} else if (!options.noTransactionDraft && (settingsStore.appSettings.autoSaveTransactionDraft === 'enabled' || settingsStore.appSettings.autoSaveTransactionDraft === 'confirmation') && transactionsStore.transactionDraft) {
setTransaction(Transaction.ofDraft(transactionsStore.transactionDraft), options, false, false);
setTransaction(Transaction.ofDraft(transactionsStore.transactionDraft), options, false);
}
if (settingsStore.appSettings.autoGetCurrentGeoLocation
@@ -809,7 +813,7 @@ function open(options: TransactionEditOptions): Promise<TransactionEditResponse
if (options && options.id) {
if (options.currentTemplate) {
setTransaction(options.currentTemplate, options, false, false);
setTransaction(options.currentTemplate, options, false);
(transaction.value as TransactionTemplate).fillFrom(options.currentTemplate);
}
@@ -850,11 +854,11 @@ function open(options: TransactionEditOptions): Promise<TransactionEditResponse
if (props.type === TransactionEditPageType.Transaction && options && options.id && responses[3] && responses[3] instanceof Transaction) {
const transaction: Transaction = responses[3];
setTransaction(transaction, options, true, true);
setTransaction(transaction, options, true);
originalTransactionEditable.value = transaction.editable;
} else if (props.type === TransactionEditPageType.Template && options && options.id && responses[3] && responses[3] instanceof TransactionTemplate) {
const template: TransactionTemplate = responses[3];
setTransaction(template, options, false, false);
setTransaction(template, options, false);
if (!(transaction.value instanceof TransactionTemplate)) {
transaction.value = TransactionTemplate.createNewTransactionTemplate(transaction.value);
@@ -862,7 +866,7 @@ function open(options: TransactionEditOptions): Promise<TransactionEditResponse
(transaction.value as TransactionTemplate).fillFrom(template);
} else {
setTransaction(null, options, true, true);
setTransaction(null, options, true);
}
loading.value = false;
@@ -1003,7 +1007,7 @@ function duplicate(withTime?: boolean, withGeoLocation?: boolean): void {
if (!withTime) {
transaction.value.time = getCurrentUnixTime();
transaction.value.timeZone = settingsStore.appSettings.timeZone;
transaction.value.utcOffset = getTimezoneOffsetMinutes(transaction.value.timeZone);
transaction.value.utcOffset = getTimezoneOffsetMinutes(transaction.value.time, transaction.value.timeZone);
}
if (!withGeoLocation) {
@@ -218,6 +218,7 @@ import { type UserExternalAuthInfoResponse } from '@/models/user_external_auth.t
import { type TokenInfoResponse, SessionDeviceType, SessionInfo } from '@/models/token.ts';
import { isEquals } from '@/lib/common.ts';
import { parseDateTimeFromUnixTime } from '@/lib/datetime.ts';
import { parseSessionInfo } from '@/lib/session.ts';
import {
isAPITokenEnabled,
@@ -253,7 +254,7 @@ class DesktopPageLinkedThirdPartyLogin {
this.externalAuthType = externalAuthInfoResponse.externalAuthType;
this.linked = externalAuthInfoResponse.linked;
this.externalUsername = externalAuthInfoResponse.externalUsername ? externalAuthInfoResponse.externalUsername : '-';
this.createdAt = externalAuthInfoResponse.createdAt ? formatUnixTimeToLongDateTime(externalAuthInfoResponse.createdAt) : '-';
this.createdAt = externalAuthInfoResponse.createdAt ? formatDateTimeToLongDateTime(parseDateTimeFromUnixTime(externalAuthInfoResponse.createdAt)) : '-';
if (externalAuthInfoResponse.externalAuthCategory === 'oauth2') {
this.displayName = getLocalizedOAuth2ProviderName(externalAuthInfoResponse.externalAuthType, getOIDCCustomDisplayNames());
@@ -277,7 +278,7 @@ class DesktopPageSessionInfo extends SessionInfo {
public constructor(sessionInfo: SessionInfo) {
super(sessionInfo.tokenId, sessionInfo.isCurrent, sessionInfo.deviceType, sessionInfo.deviceInfo, sessionInfo.deviceName, sessionInfo.lastSeen);
this.icon = this.getTokenIcon(sessionInfo.deviceType);
this.lastSeenDateTime = sessionInfo.lastSeen ? formatUnixTimeToLongDateTime(sessionInfo.lastSeen) : '-';
this.lastSeenDateTime = sessionInfo.lastSeen ? formatDateTimeToLongDateTime(parseDateTimeFromUnixTime(sessionInfo.lastSeen)) : '-';
}
private getTokenIcon(deviceType: SessionDeviceType): string {
@@ -306,7 +307,7 @@ type SnackBarType = InstanceType<typeof SnackBar>;
const {
tt,
formatUnixTimeToLongDateTime,
formatDateTimeToLongDateTime,
getLocalizedOAuth2ProviderName,
setLanguage
} = useI18n();
+8 -3
View File
@@ -129,6 +129,7 @@ import { useUserStore } from '@/stores/user.ts';
import { useExchangeRatesStore } from '@/stores/exchangeRates.ts';
import { findNameByValue } from '@/lib/common.ts';
import { parseDateTimeFromUnixTime } from '@/lib/datetime.ts';
import { getClientDisplayVersion, getDesktopVersionPath } from '@/lib/version.ts';
import { isUserScheduledTransactionEnabled } from '@/lib/server_settings.ts';
import { setExpenseAndIncomeAmountColor } from '@/lib/ui/common.ts';
@@ -137,7 +138,7 @@ const props = defineProps<{
f7router: Router.Router;
}>();
const { tt, formatUnixTimeToLongDate, initLocale } = useI18n();
const { tt, formatDateTimeToLongDate, initLocale } = useI18n();
const { showToast, showConfirm } = useI18nUIComponents();
const { allThemes, allTimezones, timeZone, isAutoUpdateExchangeRatesData, showAccountBalance } = useAppSettingPageBase();
@@ -197,8 +198,12 @@ const isEnableAnimate = computed<boolean>({
const isEnableApplicationLock = computed<boolean>(() => settingsStore.appSettings.applicationLock);
const exchangeRatesLastUpdateDate = computed<string>(() => {
const exchangeRatesLastUpdateTime = exchangeRatesStore.exchangeRatesLastUpdateTime;
return exchangeRatesLastUpdateTime ? formatUnixTimeToLongDate(exchangeRatesLastUpdateTime) : '';
if (!exchangeRatesStore.exchangeRatesLastUpdateTime) {
return '';
}
const exchangeRatesLastUpdateTime = parseDateTimeFromUnixTime(exchangeRatesStore.exchangeRatesLastUpdateTime);
return formatDateTimeToLongDate(exchangeRatesLastUpdateTime);
});
function switchToDesktopVersion(): void {
+15 -8
View File
@@ -233,8 +233,10 @@
</div>
</template>
<date-time-selection-sheet :init-mode="accountContext.balanceDateTimeSheetMode"
:timezone-utc-offset="getDefaultTimezoneOffsetMinutes(account)"
:model-value="account.balanceTime"
v-model:show="accountContext.showBalanceDateTimeSheet"
v-model="account.balanceTime">
@update:model-value="updateAccountBalanceTime(account, $event)">
</date-time-selection-sheet>
</f7-list-item>
@@ -475,8 +477,10 @@
</div>
</template>
<date-time-selection-sheet :init-mode="subAccountContexts[idx]!.balanceDateTimeSheetMode"
:timezone-utc-offset="getDefaultTimezoneOffsetMinutes(subAccount)"
:model-value="subAccount.balanceTime"
v-model:show="subAccountContexts[idx]!.showBalanceDateTimeSheet"
v-model="subAccount.balanceTime">
@update:model-value="updateAccountBalanceTime(subAccount, $event)">
</date-time-selection-sheet>
</f7-list-item>
@@ -538,8 +542,7 @@ import { isDefined, findDisplayNameByType } from '@/lib/common.ts';
import { generateRandomUUID } from '@/lib/misc.ts';
import {
getTimezoneOffsetMinutes,
getBrowserTimezoneOffsetMinutes,
getActualUnixTimeForStore
parseDateTimeFromUnixTimeWithTimezoneOffset
} from '@/lib/datetime.ts';
interface AccountContext {
@@ -561,8 +564,8 @@ const {
tt,
getAllCurrencies,
getCurrencyName,
formatUnixTimeToLongDate,
formatUnixTimeToLongTime,
formatDateTimeToLongDate,
formatDateTimeToLongTime,
formatAmountToLocalizedNumeralsWithCurrency
} = useI18n();
@@ -582,7 +585,9 @@ const {
allAccountTypes,
allAvailableMonthDays,
isAccountSupportCreditCardStatementDate,
getDefaultTimezoneOffsetMinutes,
getAccountCreditCardStatementDate,
updateAccountBalanceTime,
isNewAccount,
addSubAccount,
setAccount
@@ -621,7 +626,8 @@ function formatAccountBalanceDate(account: Account): string {
return '';
}
return formatUnixTimeToLongDate(getActualUnixTimeForStore(account.balanceTime, getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes()));
const dateTime = parseDateTimeFromUnixTimeWithTimezoneOffset(account.balanceTime, getTimezoneOffsetMinutes(account.balanceTime));
return formatDateTimeToLongDate(dateTime);
}
function formatAccountBalanceTime(account: Account): string {
@@ -629,7 +635,8 @@ function formatAccountBalanceTime(account: Account): string {
return '';
}
return formatUnixTimeToLongTime(getActualUnixTimeForStore(account.balanceTime, getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes()));
const dateTime = parseDateTimeFromUnixTimeWithTimezoneOffset(account.balanceTime, getTimezoneOffsetMinutes(account.balanceTime));
return formatDateTimeToLongTime(dateTime);
}
function init(): void {
@@ -51,10 +51,10 @@
</template>
<template #footer>
<div v-if="dateRange.isUserCustomRange && queryDateRangeType === dateRange.type && startTime && endTime">
<span>{{ displayStartTime }}</span>
<span>{{ displayStartDateTime }}</span>
<span>&nbsp;-&nbsp;</span>
<br/>
<span>{{ displayEndTime }}</span>
<span>{{ displayEndDateTime }}</span>
</div>
</template>
</f7-list-item>
@@ -227,7 +227,7 @@
<div class="transaction-footer display-flex justify-content-space-between">
<div class="flex-shrink-0">
<span>{{ getDisplayTime(item.transaction) }}</span>
<span v-if="item.transaction.utcOffset !== currentTimezoneOffsetMinutes">{{ `(${getDisplayTimezone(item.transaction)})` }}</span>
<span style="margin-inline-start: 4px" v-if="!isSameAsDefaultTimezoneOffsetMinutes(item.transaction)">{{ `(${getDisplayTimezone(item.transaction)})` }}</span>
</div>
<div class="account-balance flex-shrink-1">
<span>{{ isCurrentLiabilityAccount ? tt('Outstanding Balance') : tt('Balance') }}</span>
@@ -388,7 +388,6 @@ const {
tt,
getCurrentLanguageTextDirection,
getAllDateRanges,
formatUnixTimeToLongDateTime,
formatNumberToLocalizedNumerals
} = useI18n();
@@ -402,7 +401,6 @@ const {
firstDayOfWeek,
fiscalYearStart,
allDateAggregationTypes,
currentTimezoneOffsetMinutes,
isCurrentLiabilityAccount,
currentAccount,
currentAccountCurrency,
@@ -416,6 +414,7 @@ const {
setReconciliationStatements,
getDisplayDate,
getDisplayTime,
isSameAsDefaultTimezoneOffsetMinutes,
getDisplayTimezone,
getDisplaySourceAmount,
getDisplayDestinationAmount,
@@ -446,8 +445,6 @@ const virtualDataItems = ref<ReconciliationStatementVirtualListData>({
const textDirection = computed<TextDirection>(() => getCurrentLanguageTextDirection());
const validQuery = computed(() => currentAccount.value && currentAccount.value.type === AccountType.SingleAccount.type);
const allAvailableDateRanges = computed(() => getAllDateRanges(DateRangeScene.Normal, true, !!accountsStore.getAccountStatementDate(accountId.value)));
const displayStartTime = computed<string>(() => formatUnixTimeToLongDateTime(startTime.value));
const displayEndTime = computed<string>(() => formatUnixTimeToLongDateTime(endTime.value));
const allReconciliationStatementVirtualListItems = computed<ReconciliationStatementVirtualListItem[]>(() => {
const ret: ReconciliationStatementVirtualListItem[] = [];
@@ -124,8 +124,9 @@ import { useI18n } from '@/locales/helpers.ts';
import { useSettingsStore } from '@/stores/setting.ts';
import { TextDirection } from '@/core/text.ts';
import { type DateTime } from '@/core/datetime.ts';
import { FontSize } from '@/core/font.ts';
import { parseDateTimeFromUnixTime, getCurrentUnixTime } from '@/lib/datetime.ts';
import { getCurrentDateTime } from '@/lib/datetime.ts';
import { setAppFontSize, getFontSizePreviewClassName } from '@/lib/ui/mobile.ts';
const props = defineProps<{
@@ -136,23 +137,23 @@ const {
tt,
getCurrentLanguageTextDirection,
getWeekdayShortName,
getCalendarDisplayDayOfMonthFromUnixTime,
formatUnixTimeToShortTime,
formatUnixTimeToGregorianLikeLongYearMonth,
getCalendarDisplayDayOfMonthFromDateTime,
formatDateTimeToShortTime,
formatDateTimeToGregorianLikeLongYearMonth,
formatAmountToLocalizedNumeralsWithCurrency
} = useI18n();
const settingsStore = useSettingsStore();
const currentUnixTime = ref<number>(getCurrentUnixTime());
const currentDateTime = ref<DateTime>(getCurrentDateTime());
const fontSize = ref<number>(settingsStore.appSettings.fontSize);
const textDirection = computed<string>(() => getCurrentLanguageTextDirection());
const fontSizePreviewClassName = computed<string>(() => getFontSizePreviewClassName(fontSize.value));
const currentLongYearMonth = computed<string>(() => formatUnixTimeToGregorianLikeLongYearMonth(currentUnixTime.value));
const currentDayOfMonth = computed<string>(() => getCalendarDisplayDayOfMonthFromUnixTime(currentUnixTime.value));
const currentDayOfWeek = computed<string>(() => getWeekdayShortName(parseDateTimeFromUnixTime(currentUnixTime.value).getWeekDay()));
const currentShortTime = computed<string>(() => formatUnixTimeToShortTime(currentUnixTime.value));
const currentLongYearMonth = computed<string>(() => formatDateTimeToGregorianLikeLongYearMonth(currentDateTime.value));
const currentDayOfMonth = computed<string>(() => getCalendarDisplayDayOfMonthFromDateTime(currentDateTime.value));
const currentDayOfWeek = computed<string>(() => getWeekdayShortName(currentDateTime.value.getWeekDay()));
const currentShortTime = computed<string>(() => formatDateTimeToShortTime(currentDateTime.value));
function getFontSizeName(): string {
return '';
+20 -13
View File
@@ -251,8 +251,10 @@
</div>
</template>
<date-time-selection-sheet :init-mode="transactionDateTimeSheetMode"
:timezone-utc-offset="transaction.utcOffset"
:model-value="transaction.time"
v-model:show="showTransactionDateTimeSheet"
v-model="transaction.time">
@update:model-value="updateTransactionTime">
</date-time-selection-sheet>
</f7-list-item>
@@ -323,8 +325,9 @@
:filter-placeholder="tt('Timezone')"
:filter-no-items-text="tt('No results')"
:items="allTimezones"
:model-value="transaction.timeZone"
v-model:show="showTimezonePopup"
v-model="transaction.timeZone">
@update:model-value="updateTransactionTimezone">
</list-item-selection-popup>
</f7-list-item>
@@ -512,10 +515,9 @@ import type { TransactionPictureInfoBasicResponse } from '@/models/transaction_p
import { Transaction } from '@/models/transaction.ts';
import {
getActualUnixTimeForStore,
getBrowserTimezoneOffsetMinutes,
getTimezoneOffset,
getTimezoneOffsetMinutes
getTimezoneOffsetMinutes,
parseDateTimeFromUnixTimeWithTimezoneOffset
} from '@/lib/datetime.ts';
import { formatCoordinate } from '@/lib/coordinate.ts';
import { generateRandomUUID } from '@/lib/misc.ts';
@@ -536,8 +538,8 @@ const {
tt,
getMultiMonthdayShortNames,
getMultiWeekdayLongNames,
formatUnixTimeToLongDate,
formatUnixTimeToLongTime,
formatDateTimeToLongDate,
formatDateTimeToLongTime,
formatGregorianTextualYearMonthDayToLongDate,
parseAmountFromLocalizedNumerals
} = useI18n();
@@ -589,6 +591,8 @@ const {
geoLocationStatusInfo,
inputEmptyProblemMessage,
inputIsEmpty,
updateTransactionTime,
updateTransactionTimezone,
swapTransactionData,
getDisplayAmount,
getTransactionPictureUrl
@@ -655,19 +659,23 @@ const destinationAmountClass = computed<Record<string, boolean>>(() => {
const transactionDisplayDate = computed<string>(() => {
if (mode.value !== TransactionEditPageMode.View || !showTimeInDefaultTimezone.value) {
return formatUnixTimeToLongDate(getActualUnixTimeForStore(transaction.value.time, getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes()));
const dateTime = parseDateTimeFromUnixTimeWithTimezoneOffset(transaction.value.time, transaction.value.utcOffset);
return formatDateTimeToLongDate(dateTime);
}
return formatUnixTimeToLongDate(getActualUnixTimeForStore(transaction.value.time, transaction.value.utcOffset, getBrowserTimezoneOffsetMinutes()));
const dateTime = parseDateTimeFromUnixTimeWithTimezoneOffset(transaction.value.time, getTimezoneOffsetMinutes(transaction.value.time));
return formatDateTimeToLongDate(dateTime);
});
const transactionDisplayTime = computed<string>(() => {
if (mode.value !== TransactionEditPageMode.View || !showTimeInDefaultTimezone.value) {
return formatUnixTimeToLongTime(getActualUnixTimeForStore(transaction.value.time, getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes()));
const dateTime = parseDateTimeFromUnixTimeWithTimezoneOffset(transaction.value.time, transaction.value.utcOffset);
return formatDateTimeToLongTime(dateTime);
}
const utcOffset = numeralSystem.value.replaceWesternArabicDigitsToLocalizedDigits(getTimezoneOffset(settingsStore.appSettings.timeZone));
return `${formatUnixTimeToLongTime(getActualUnixTimeForStore(transaction.value.time, transaction.value.utcOffset, getBrowserTimezoneOffsetMinutes()))} (UTC${utcOffset})`;
const dateTime = parseDateTimeFromUnixTimeWithTimezoneOffset(transaction.value.time, getTimezoneOffsetMinutes(transaction.value.time));
const utcOffset = numeralSystem.value.replaceWesternArabicDigitsToLocalizedDigits(getTimezoneOffset(transaction.value.time));
return `${formatDateTimeToLongTime(dateTime)} (UTC${utcOffset})`;
});
const transactionDisplayTimezoneName = computed<string>(() => {
@@ -949,7 +957,6 @@ function init(): void {
tagIds: query['tagIds'],
comment: query['comment']
},
pageTypeAndMode.type === TransactionEditPageType.Transaction && (mode.value === TransactionEditPageMode.Edit || mode.value === TransactionEditPageMode.View),
pageTypeAndMode.type === TransactionEditPageType.Transaction && (mode.value === TransactionEditPageMode.Edit || mode.value === TransactionEditPageMode.View)
);
+8 -9
View File
@@ -205,7 +205,7 @@
<template #media>
<div class="display-flex flex-direction-column transaction-date" :style="getTransactionDateStyle(transaction, idx > 0 ? transactionMonthList.items[idx - 1] : undefined)">
<span class="transaction-day full-line flex-direction-column">
{{ getCalendarDisplayDayOfMonthFromUnixTime(transaction.time) }}
{{ transaction.gregorianCalendarDayOfMonth ? numeralSystem.formatNumber(transaction.gregorianCalendarDayOfMonth) : '' }}
</span>
<span class="transaction-day-of-week full-line flex-direction-column" v-if="transaction.displayDayOfWeek">
{{ getWeekdayShortName(transaction.displayDayOfWeek) }}
@@ -265,7 +265,7 @@
</div>
<div class="transaction-footer">
<span>{{ getDisplayTime(transaction) }}</span>
<span v-if="transaction.utcOffset !== currentTimezoneOffsetMinutes">{{ `(${getDisplayTimezone(transaction)})` }}</span>
<span v-if="!isSameAsDefaultTimezoneOffsetMinutes(transaction)">{{ `(${getDisplayTimezone(transaction)})` }}</span>
<span v-if="transaction.sourceAccount">·</span>
<span v-if="transaction.sourceAccount">{{ transaction.sourceAccount.name }}</span>
<f7-icon class="transaction-account-arrow icon-with-direction" f7="arrow_right" v-if="transaction.sourceAccount && transaction.type === TransactionType.Transfer && transaction.destinationAccount && transaction.sourceAccount.id !== transaction.destinationAccount.id"></f7-icon>
@@ -624,7 +624,7 @@ import {
DateRangeScene,
DateRange
} from '@/core/datetime.ts';
import { AmountFilterType } from '@/core/numeral.ts';
import { type NumeralSystem, AmountFilterType } from '@/core/numeral.ts';
import { TransactionType } from '@/core/transaction.ts';
import type { TransactionCategory } from '@/models/transaction_category.ts';
import { type Transaction, TransactionTagFilter } from '@/models/transaction.ts';
@@ -637,8 +637,6 @@ import {
import {
getCurrentUnixTime,
parseDateTimeFromUnixTime,
getBrowserTimezoneOffsetMinutes,
getActualUnixTimeForStore,
getDayFirstUnixTimeBySpecifiedUnixTime,
getYearMonthFirstUnixTime,
getYearMonthLastUnixTime,
@@ -664,8 +662,8 @@ const props = defineProps<{
const {
tt,
getCurrentLanguageTextDirection,
getWeekdayShortName,
getCalendarDisplayDayOfMonthFromUnixTime
getCurrentNumeralSystemType,
getWeekdayShortName
} = useI18n();
const { showAlert, showToast, routeBackOnError } = useI18nUIComponents();
@@ -676,7 +674,6 @@ const {
customMinDatetime,
customMaxDatetime,
currentCalendarDate,
currentTimezoneOffsetMinutes,
firstDayOfWeek,
fiscalYearStart,
defaultCurrency,
@@ -711,6 +708,7 @@ const {
transactionCalendarMaxDate,
currentMonthTransactionData,
hasSubCategoryInQuery,
isSameAsDefaultTimezoneOffsetMinutes,
canAddTransaction,
getDisplayTime,
getDisplayLongYearMonth,
@@ -737,6 +735,7 @@ const showCustomMonthSheet = ref<boolean>(false);
const showDeleteActionSheet = ref<boolean>(false);
const textDirection = computed<TextDirection>(() => getCurrentLanguageTextDirection());
const numeralSystem = computed<NumeralSystem>(() => getCurrentNumeralSystemType());
const isDarkMode = computed<boolean>(() => environmentsStore.framework7DarkMode || false);
const transactions = computed<TransactionMonthList[]>(() => {
@@ -1057,7 +1056,7 @@ function changePageType(type: number): void {
function changeDateFilter(dateType: number): void {
if (dateType === DateRange.Custom.type) { // Custom
if (!query.value.minTime || !query.value.maxTime) {
customMaxDatetime.value = getActualUnixTimeForStore(getCurrentUnixTime(), currentTimezoneOffsetMinutes.value, getBrowserTimezoneOffsetMinutes());
customMaxDatetime.value = getCurrentUnixTime();
customMinDatetime.value = getDayFirstUnixTimeBySpecifiedUnixTime(customMaxDatetime.value);
} else {
customMaxDatetime.value = query.value.maxTime;
+8 -2
View File
@@ -58,6 +58,7 @@ import { TextDirection } from '@/core/text.ts';
import { type TokenInfoResponse, SessionDeviceType, SessionInfo } from '@/models/token.ts';
import { isEquals } from '@/lib/common.ts';
import { parseDateTimeFromUnixTime } from '@/lib/datetime.ts';
import { parseSessionInfo } from '@/lib/session.ts';
class MobilePageSessionInfo extends SessionInfo {
@@ -69,7 +70,7 @@ class MobilePageSessionInfo extends SessionInfo {
super(sessionInfo.tokenId, sessionInfo.isCurrent, sessionInfo.deviceType, sessionInfo.deviceInfo, sessionInfo.deviceName, sessionInfo.lastSeen);
this.domId = getTokenDomId(sessionInfo.tokenId);
this.icon = getTokenIcon(sessionInfo.deviceType);
this.lastSeenDateTime = sessionInfo.lastSeen ? formatUnixTimeToLongDateTime(sessionInfo.lastSeen) : '-';
this.lastSeenDateTime = sessionInfo.lastSeen ? formatDateTimeToLongDateTime(parseDateTimeFromUnixTime(sessionInfo.lastSeen)) : '-';
}
}
@@ -77,7 +78,12 @@ const props = defineProps<{
f7router: Router.Router;
}>();
const { tt, getCurrentLanguageTextDirection, formatUnixTimeToLongDateTime } = useI18n();
const {
tt,
getCurrentLanguageTextDirection,
formatDateTimeToLongDateTime
} = useI18n();
const { showConfirm, showToast, routeBackOnError } = useI18nUIComponents();
const tokensStore = useTokensStore();