diff --git a/cmd/user_data.go b/cmd/user_data.go index 07d5548f..610a8933 100644 --- a/cmd/user_data.go +++ b/cmd/user_data.go @@ -946,6 +946,8 @@ func printUserInfo(user *models.User) { fmt.Printf("[DefaultCurrency] %s\n", user.DefaultCurrency) fmt.Printf("[FirstDayOfWeek] %s (%d)\n", user.FirstDayOfWeek, user.FirstDayOfWeek) fmt.Printf("[FiscalYearStart] %s (%d)\n", user.FiscalYearStart, user.FiscalYearStart) + fmt.Printf("[CalendarDisplayType] %s (%d)\n", user.CalendarDisplayType, user.CalendarDisplayType) + fmt.Printf("[DateDisplayType] %s (%d)\n", user.DateDisplayType, user.DateDisplayType) fmt.Printf("[LongDateFormat] %s (%d)\n", user.LongDateFormat, user.LongDateFormat) fmt.Printf("[ShortDateFormat] %s (%d)\n", user.ShortDateFormat, user.ShortDateFormat) fmt.Printf("[LongTimeFormat] %s (%d)\n", user.LongTimeFormat, user.LongTimeFormat) diff --git a/pkg/api/users.go b/pkg/api/users.go index 93871546..cdfee61f 100644 --- a/pkg/api/users.go +++ b/pkg/api/users.go @@ -359,6 +359,24 @@ func (a *UsersApi) UserUpdateProfileHandler(c *core.WebContext) (any, *errs.Erro userNew.FiscalYearStart = core.FISCAL_YEAR_START_INVALID } + if userUpdateReq.CalendarDisplayType != nil && *userUpdateReq.CalendarDisplayType != user.CalendarDisplayType { + user.CalendarDisplayType = *userUpdateReq.CalendarDisplayType + userNew.CalendarDisplayType = *userUpdateReq.CalendarDisplayType + modifyProfileBasicInfo = true + anythingUpdate = true + } else { + userNew.CalendarDisplayType = core.CALENDAR_DISPLAY_TYPE_INVALID + } + + if userUpdateReq.DateDisplayType != nil && *userUpdateReq.DateDisplayType != user.DateDisplayType { + user.DateDisplayType = *userUpdateReq.DateDisplayType + userNew.DateDisplayType = *userUpdateReq.DateDisplayType + modifyProfileBasicInfo = true + anythingUpdate = true + } else { + userNew.DateDisplayType = core.DATE_DISPLAY_TYPE_INVALID + } + if userUpdateReq.LongDateFormat != nil && *userUpdateReq.LongDateFormat != user.LongDateFormat { user.LongDateFormat = *userUpdateReq.LongDateFormat userNew.LongDateFormat = *userUpdateReq.LongDateFormat diff --git a/pkg/core/calendar.go b/pkg/core/calendar.go new file mode 100644 index 00000000..4bd5f988 --- /dev/null +++ b/pkg/core/calendar.go @@ -0,0 +1,54 @@ +package core + +import "fmt" + +// CalendarDisplayType represents calendar display type +type CalendarDisplayType byte + +// Calendar Display Type +const ( + CALENDAR_DISPLAY_TYPE_DEFAULT CalendarDisplayType = 0 + CALENDAR_DISPLAY_TYPE_GREGORAIN CalendarDisplayType = 1 + CALENDAR_DISPLAY_TYPE_INVALID CalendarDisplayType = 255 +) + +// String returns a textual representation of the calendar display type enum +func (f CalendarDisplayType) String() string { + switch f { + case CALENDAR_DISPLAY_TYPE_DEFAULT: + return "Default" + case CALENDAR_DISPLAY_TYPE_GREGORAIN: + return "Gregorian" + case CALENDAR_DISPLAY_TYPE_INVALID: + return "Invalid" + default: + return fmt.Sprintf("Invalid(%d)", int(f)) + } +} + +// DateDisplayType represents date display type +type DateDisplayType byte + +// Date Display Type +const ( + DATE_DISPLAY_TYPE_DEFAULT DateDisplayType = 0 + DATE_DISPLAY_TYPE_GREGORAIN DateDisplayType = 1 + DATE_DISPLAY_TYPE_BUDDHIST DateDisplayType = 2 + DATE_DISPLAY_TYPE_INVALID DateDisplayType = 255 +) + +// String returns a textual representation of the date display type enum +func (f DateDisplayType) String() string { + switch f { + case DATE_DISPLAY_TYPE_DEFAULT: + return "Default" + case DATE_DISPLAY_TYPE_GREGORAIN: + return "Gregorian" + case DATE_DISPLAY_TYPE_BUDDHIST: + return "Buddhist" + case DATE_DISPLAY_TYPE_INVALID: + return "Invalid" + default: + return fmt.Sprintf("Invalid(%d)", int(f)) + } +} diff --git a/pkg/models/user.go b/pkg/models/user.go index 5295ee0e..b84b4c30 100644 --- a/pkg/models/user.go +++ b/pkg/models/user.go @@ -95,6 +95,8 @@ type User struct { DefaultCurrency string `xorm:"VARCHAR(3) NOT NULL"` FirstDayOfWeek core.WeekDay `xorm:"TINYINT NOT NULL"` FiscalYearStart core.FiscalYearStart `xorm:"SMALLINT"` + CalendarDisplayType core.CalendarDisplayType `xorm:"TINYINT"` + DateDisplayType core.DateDisplayType `xorm:"TINYINT"` LongDateFormat core.LongDateFormat `xorm:"TINYINT"` ShortDateFormat core.ShortDateFormat `xorm:"TINYINT"` LongTimeFormat core.LongTimeFormat `xorm:"TINYINT"` @@ -131,6 +133,8 @@ type UserBasicInfo struct { DefaultCurrency string `json:"defaultCurrency"` FirstDayOfWeek core.WeekDay `json:"firstDayOfWeek"` FiscalYearStart core.FiscalYearStart `json:"fiscalYearStart"` + CalendarDisplayType core.CalendarDisplayType `json:"calendarDisplayType"` + DateDisplayType core.DateDisplayType `json:"dateDisplayType"` LongDateFormat core.LongDateFormat `json:"longDateFormat"` ShortDateFormat core.ShortDateFormat `json:"shortDateFormat"` LongTimeFormat core.LongTimeFormat `json:"longTimeFormat"` @@ -195,6 +199,8 @@ type UserProfileUpdateRequest struct { DefaultCurrency string `json:"defaultCurrency" binding:"omitempty,len=3,validCurrency"` FirstDayOfWeek *core.WeekDay `json:"firstDayOfWeek" binding:"omitempty,min=0,max=6"` FiscalYearStart *core.FiscalYearStart `json:"fiscalYearStart" binding:"omitempty,validFiscalYearStart"` + CalendarDisplayType *core.CalendarDisplayType `json:"calendarDisplayType" binding:"omitempty,min=0,max=1"` + DateDisplayType *core.DateDisplayType `json:"dateDisplayType" binding:"omitempty,min=0,max=2"` LongDateFormat *core.LongDateFormat `json:"longDateFormat" binding:"omitempty,min=0,max=3"` ShortDateFormat *core.ShortDateFormat `json:"shortDateFormat" binding:"omitempty,min=0,max=3"` LongTimeFormat *core.LongTimeFormat `json:"longTimeFormat" binding:"omitempty,min=0,max=3"` @@ -284,6 +290,8 @@ func (u *User) ToUserBasicInfo(avatarProvider core.UserAvatarProviderType, avata DefaultCurrency: u.DefaultCurrency, FirstDayOfWeek: u.FirstDayOfWeek, FiscalYearStart: fiscalYearStart, + CalendarDisplayType: u.CalendarDisplayType, + DateDisplayType: u.DateDisplayType, LongDateFormat: u.LongDateFormat, ShortDateFormat: u.ShortDateFormat, LongTimeFormat: u.LongTimeFormat, diff --git a/pkg/services/users.go b/pkg/services/users.go index d3726958..a4147ff5 100644 --- a/pkg/services/users.go +++ b/pkg/services/users.go @@ -293,6 +293,14 @@ func (s *UserService) UpdateUser(c core.Context, user *models.User, modifyUserLa updateCols = append(updateCols, "fiscal_year_start") } + if core.CALENDAR_DISPLAY_TYPE_DEFAULT <= user.CalendarDisplayType && user.CalendarDisplayType <= core.CALENDAR_DISPLAY_TYPE_GREGORAIN { + updateCols = append(updateCols, "calendar_type") + } + + if core.DATE_DISPLAY_TYPE_DEFAULT <= user.DateDisplayType && user.DateDisplayType <= core.DATE_DISPLAY_TYPE_BUDDHIST { + updateCols = append(updateCols, "date_display_type") + } + if core.LONG_DATE_FORMAT_DEFAULT <= user.LongDateFormat && user.LongDateFormat <= core.LONG_DATE_FORMAT_D_M_YYYY { updateCols = append(updateCols, "long_date_format") } diff --git a/src/core/calendar.ts b/src/core/calendar.ts new file mode 100644 index 00000000..12f8cfd2 --- /dev/null +++ b/src/core/calendar.ts @@ -0,0 +1,88 @@ +import type { TypeAndName } from '@/core/base.ts'; + +export enum CalendarType { + Gregorian = 0, + Buddhist = 1, + Chinese = 2 +} + +export class CalendarDisplayType implements TypeAndName { + private static readonly allInstances: CalendarDisplayType[] = []; + private static readonly allInstancesByType: Record = {}; + private static readonly allInstancesByTypeName: Record = {}; + + public static readonly LanguageDefaultType: number = 0; + public static readonly Gregorian = new CalendarDisplayType(1, 'Gregorian', 'Gregorian', CalendarType.Gregorian); + + public static readonly Default = CalendarDisplayType.Gregorian; + + public readonly type: number; + public readonly typeName: string; + public readonly name: string; + public readonly primaryCalendarType: CalendarType; + public readonly secondaryCalendarType?: CalendarType; + + private constructor(type: number, typeName: string, name: string, primaryCalendarType: CalendarType, secondaryCalendarType?: CalendarType) { + this.type = type; + this.typeName = typeName; + this.name = name; + this.primaryCalendarType = primaryCalendarType; + this.secondaryCalendarType = secondaryCalendarType; + + CalendarDisplayType.allInstances.push(this); + CalendarDisplayType.allInstancesByType[type] = this; + CalendarDisplayType.allInstancesByTypeName[typeName] = this; + } + + public static values(): CalendarDisplayType[] { + return CalendarDisplayType.allInstances; + } + + public static valueOf(type: number): CalendarDisplayType | undefined { + return CalendarDisplayType.allInstancesByType[type]; + } + + public static parse(typeName: string): CalendarDisplayType | undefined { + return CalendarDisplayType.allInstancesByTypeName[typeName]; + } +} + +export class DateDisplayType implements TypeAndName { + private static readonly allInstances: DateDisplayType[] = []; + private static readonly allInstancesByType: Record = {}; + private static readonly allInstancesByTypeName: Record = {}; + + public static readonly LanguageDefaultType: number = 0; + public static readonly Gregorian = new DateDisplayType(1, 'Gregorian', 'Gregorian', CalendarType.Gregorian); + public static readonly Chinese = new DateDisplayType(2, 'Buddhist', 'Buddhist', CalendarType.Buddhist); + + public static readonly Default = DateDisplayType.Gregorian; + + public readonly type: number; + public readonly typeName: string; + public readonly name: string; + public readonly calendarType: CalendarType; + + private constructor(type: number, typeName: string, name: string, calendarType: CalendarType) { + this.type = type; + this.typeName = typeName; + this.name = name; + this.calendarType = calendarType; + + DateDisplayType.allInstances.push(this); + DateDisplayType.allInstancesByType[type] = this; + DateDisplayType.allInstancesByTypeName[typeName] = this; + } + + public static values(): DateDisplayType[] { + return DateDisplayType.allInstances; + } + + public static valueOf(type: number): DateDisplayType | undefined { + return DateDisplayType.allInstancesByType[type]; + } + + public static parse(typeName: string): DateDisplayType | undefined { + return DateDisplayType.allInstancesByTypeName[typeName]; + } +} diff --git a/src/core/datetime.ts b/src/core/datetime.ts index ae599155..53055320 100644 --- a/src/core/datetime.ts +++ b/src/core/datetime.ts @@ -1,33 +1,50 @@ import type { TypeAndName, TypeAndDisplayName } from '@/core/base.ts'; +import type { CalendarType } from '@/core/calendar.ts'; +import type { NumeralSystem } from '@/core/numeral.ts'; export interface DateTime { getUnixTime(): number; - getLocalizedCalendarYear(): number; + getLocalizedCalendarYear(options: DateTimeFormatOptions): number; getGregorianCalendarYear(): number; getGregorianCalendarQuarter(): number; - getLocalizedCalendarQuarter(): number; + getLocalizedCalendarQuarter(options: DateTimeFormatOptions): number; getGregorianCalendarMonth(): number; - getGregorianCalendarMonthDisplayName(): string; - getGregorianCalendarMonthDisplayShortName(): string; - getLocalizedCalendarMonth(): number; - getLocalizedCalendarMonthDisplayName(): string; - getLocalizedCalendarMonthDisplayShortName(): string; + getGregorianCalendarMonthDisplayName(options: DateTimeFormatOptions): string; + getGregorianCalendarMonthDisplayShortName(options: DateTimeFormatOptions): string; + getLocalizedCalendarMonth(options: DateTimeFormatOptions): number; + getLocalizedCalendarMonthDisplayName(options: DateTimeFormatOptions): string; + getLocalizedCalendarMonthDisplayShortName(options: DateTimeFormatOptions): string; getGregorianCalendarDay(): number; - getLocalizedCalendarDay(): number; + getLocalizedCalendarDay(options: DateTimeFormatOptions): number; getGregorianCalendarYearDashMonthDashDay(): TextualYearMonthDay; getGregorianCalendarYearDashMonth(): TextualYearMonth; getWeekDay(): WeekDay; - getWeekDayDisplayName(): string - getWeekDayDisplayShortName(): string; - getWeekDayDisplayMinName(): string; + getWeekDayDisplayName(options: DateTimeFormatOptions): string + getWeekDayDisplayShortName(options: DateTimeFormatOptions): string; + getWeekDayDisplayMinName(options: DateTimeFormatOptions): string; getHour(): number; getMinute(): number; getSecond(): number; - getDisplayAMPM(): string; + getDisplayAMPM(options: DateTimeFormatOptions): string; getTimezoneUtcOffsetMinutes(): number; toGregorianCalendarYearMonthDay(): YearMonthDay; toGregorianCalendarYear0BasedMonth(): Year0BasedMonth; - format(format: string): string; + format(format: string, options: DateTimeFormatOptions): string; +} + +export interface DateTimeFormatOptions { + calendarType: CalendarType; + numeralSystem: NumeralSystem; + localeData: DateTimeLocaleData; +} + +export interface DateTimeLocaleData { + months: () => string[]; + monthsShort: () => string[]; + weekdays: () => string[]; + weekdaysShort: () => string[]; + weekdaysMin: () => string[]; + meridiem: (hour: number, minute: number, isLower: boolean) => string; } export type TextualYearMonth = `${number}-${number}`; diff --git a/src/lib/__tests__/fiscal_year.ts b/src/lib/__tests__/fiscal_year.ts index 1667c8dd..7e357494 100644 --- a/src/lib/__tests__/fiscal_year.ts +++ b/src/lib/__tests__/fiscal_year.ts @@ -14,8 +14,7 @@ import { getFiscalYearEndUnixTime, getFiscalYearTimeRangeFromUnixTime, getAllFiscalYearsStartAndEndUnixTimes, - getFiscalYearTimeRangeFromYear, - formatUnixTime + getFiscalYearTimeRangeFromYear } from '@/lib/datetime.ts'; // Set test environment timezone to UTC, since the test data constants are in UTC @@ -35,7 +34,7 @@ function importTestData(datasetName: string): unknown[] { } function formatUnixTimeISO(unixTime: number): string { - return formatUnixTime(unixTime, 'YYYY-MM-DDTHH:mm:ssZ'); + return moment.unix(unixTime).format('YYYY-MM-DDTHH:mm:ssZ'); } function getTestTitleFormatDate(testFiscalYearStartId: string, testCaseDateString: string): string { diff --git a/src/lib/common.ts b/src/lib/common.ts index 24dac63e..d215da5b 100644 --- a/src/lib/common.ts +++ b/src/lib/common.ts @@ -156,6 +156,10 @@ export function isObjectEmpty(obj: object): boolean { return true; } +export function ofObject(object: T): T { + return object; +} + export function getNumberValue(value: unknown, defaultValue: number): number { if (isString(value)) { return parseInt(value, 10); diff --git a/src/lib/datetime.ts b/src/lib/datetime.ts index 72c6c1b3..a1f5c07e 100644 --- a/src/lib/datetime.ts +++ b/src/lib/datetime.ts @@ -1,8 +1,12 @@ import moment from 'moment-timezone'; import { type unitOfTime } from 'moment/moment'; +import { + CalendarType +} from '@/core/calendar.ts'; import { type DateTime, + type DateTimeFormatOptions, type TextualYearMonth, type TextualYearMonthDay, type YearUnixTime, @@ -34,36 +38,44 @@ import { } from '@/core/fiscalyear.ts'; import { isFunction, + isDefined, isObject, isString, - isNumber + isNumber, + ofObject } from './common.ts'; -type DateTimeTokenFormatFunction = (d: MomentDateTime) => string; +interface DateTimeFormatResult { + value: number | string; + numeralLength?: number; + hasNumeral?: boolean; +} + +type DateTimeTokenFormatFunction = (d: MomentDateTime, options: DateTimeFormatOptions) => DateTimeFormatResult class MomentDateTime implements DateTime { private static readonly tokenFormatFuncs: Record = { - 'YY': (d: MomentDateTime) => (d.getLocalizedCalendarYear() % 100).toString().padStart(2, '0'), - 'YYYY': (d: MomentDateTime) => d.getLocalizedCalendarYear().toString().padStart(4, '0'), - 'M': (d: MomentDateTime) => d.getLocalizedCalendarMonth().toString(), - 'MM': (d: MomentDateTime) => d.getLocalizedCalendarMonth().toString().padStart(2, '0'), - 'MMM': (d: MomentDateTime) => d.getLocalizedCalendarMonthDisplayShortName(), - 'MMMM': (d: MomentDateTime) => d.getLocalizedCalendarMonthDisplayName(), - 'D': (d: MomentDateTime) => d.getLocalizedCalendarDay().toString(), - 'DD': (d: MomentDateTime) => d.getLocalizedCalendarDay().toString().padStart(2, '0'), - 'dd': (d: MomentDateTime) => d.getWeekDayDisplayMinName(), - 'ddd': (d: MomentDateTime) => d.getWeekDayDisplayShortName(), - 'dddd': (d: MomentDateTime) => d.getWeekDayDisplayName(), - 'H': (d: MomentDateTime) => d.getHour().toString(), - 'HH': (d: MomentDateTime) => d.getHour().toString().padStart(2, '0'), - 'h': (d: MomentDateTime) => getHourIn12HourFormat(d.getHour()).toString(), - 'hh': (d: MomentDateTime) => getHourIn12HourFormat(d.getHour()).toString().padStart(2, '0'), - 'm': (d: MomentDateTime) => d.getMinute().toString(), - 'mm': (d: MomentDateTime) => d.getMinute().toString().padStart(2, '0'), - 's': (d: MomentDateTime) => d.getSecond().toString(), - 'ss': (d: MomentDateTime) => d.getSecond().toString().padStart(2, '0'), - 'A': (d: MomentDateTime) => d.getDisplayAMPM(), - 'Z': (d: MomentDateTime) => getUtcOffsetByUtcOffsetMinutes(d.getTimezoneUtcOffsetMinutes()) + 'YY': (d: MomentDateTime, options: DateTimeFormatOptions) => ofObject({ value: d.getLocalizedCalendarYear(options) % 100, numeralLength: 2 }), + 'YYYY': (d: MomentDateTime, options: DateTimeFormatOptions) => ofObject({ value: d.getLocalizedCalendarYear(options), numeralLength: 4 }), + 'M': (d: MomentDateTime, options: DateTimeFormatOptions) => ofObject({ value: d.getLocalizedCalendarMonth(options) }), + 'MM': (d: MomentDateTime, options: DateTimeFormatOptions) => ofObject({ value: d.getLocalizedCalendarMonth(options), numeralLength: 2 }), + 'MMM': (d: MomentDateTime, options: DateTimeFormatOptions) => ofObject({ value: d.getLocalizedCalendarMonthDisplayShortName(options) }), + 'MMMM': (d: MomentDateTime, options: DateTimeFormatOptions) => ofObject({ value: d.getLocalizedCalendarMonthDisplayName(options) }), + 'D': (d: MomentDateTime, options: DateTimeFormatOptions) => ofObject({ value: d.getLocalizedCalendarDay(options) }), + 'DD': (d: MomentDateTime, options: DateTimeFormatOptions) => ofObject({ value: d.getLocalizedCalendarDay(options), numeralLength: 2 }), + 'dd': (d: MomentDateTime, options: DateTimeFormatOptions) => ofObject({ value: d.getWeekDayDisplayMinName(options) }), + 'ddd': (d: MomentDateTime, options: DateTimeFormatOptions) => ofObject({ value: d.getWeekDayDisplayShortName(options) }), + 'dddd': (d: MomentDateTime, options: DateTimeFormatOptions) => ofObject({ value: d.getWeekDayDisplayName(options) }), + 'H': (d: MomentDateTime) => ofObject({ value: d.getHour() }), + 'HH': (d: MomentDateTime) => ofObject({ value: d.getHour(), numeralLength: 2 }), + 'h': (d: MomentDateTime) => ofObject({ value: getHourIn12HourFormat(d.getHour()) }), + 'hh': (d: MomentDateTime) => ofObject({ value: getHourIn12HourFormat(d.getHour()), numeralLength: 2 }), + 'm': (d: MomentDateTime) => ofObject({ value: d.getMinute() }), + 'mm': (d: MomentDateTime) => ofObject({ value: d.getMinute(), numeralLength: 2 }), + 's': (d: MomentDateTime) => ofObject({ value: d.getSecond() }), + 'ss': (d: MomentDateTime) => ofObject({ value: d.getSecond(), numeralLength: 2 }), + 'A': (d: MomentDateTime, options: DateTimeFormatOptions) => ofObject({ value: d.getDisplayAMPM(options) }), + 'Z': (d: MomentDateTime) => ofObject({ value: getUtcOffsetByUtcOffsetMinutes(d.getTimezoneUtcOffsetMinutes()), hasNumeral: true }), }; private readonly instance: moment.Moment; @@ -76,7 +88,11 @@ class MomentDateTime implements DateTime { return this.instance.unix(); } - public getLocalizedCalendarYear(): number { + public getLocalizedCalendarYear(options: DateTimeFormatOptions): number { + if (options && options.calendarType === CalendarType.Buddhist) { + return this.instance.year() + 543; + } + return this.instance.year(); } @@ -88,7 +104,8 @@ class MomentDateTime implements DateTime { return this.instance.quarter(); } - public getLocalizedCalendarQuarter(): number { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + public getLocalizedCalendarQuarter(options: DateTimeFormatOptions): number { return this.instance.quarter(); } @@ -96,35 +113,53 @@ class MomentDateTime implements DateTime { return this.instance.month() + 1; } - public getGregorianCalendarMonthDisplayName(): string { - const names = this.instance.localeData().months(); + public getGregorianCalendarMonthDisplayName(options: DateTimeFormatOptions): string { + if (!options || !options.localeData) { + return ''; + } + + const names = options.localeData.months(); return names[this.getGregorianCalendarMonth() - 1] || ''; } - public getGregorianCalendarMonthDisplayShortName(): string { - const names = this.instance.localeData().monthsShort(); + public getGregorianCalendarMonthDisplayShortName(options: DateTimeFormatOptions): string { + if (!options || !options.localeData) { + return ''; + } + + const names = options.localeData.monthsShort(); return names[this.getGregorianCalendarMonth() - 1] || ''; } - public getLocalizedCalendarMonth(): number { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + public getLocalizedCalendarMonth(options: DateTimeFormatOptions): number { return this.instance.month() + 1; } - public getLocalizedCalendarMonthDisplayName(): string { - const names = this.instance.localeData().months(); - return names[this.getLocalizedCalendarMonth() - 1] || ''; + public getLocalizedCalendarMonthDisplayName(options: DateTimeFormatOptions): string { + if (!options || !options.localeData) { + return ''; + } + + const names = options.localeData.months(); + return names[this.getLocalizedCalendarMonth(options) - 1] || ''; } - public getLocalizedCalendarMonthDisplayShortName(): string { - const names = this.instance.localeData().monthsShort(); - return names[this.getLocalizedCalendarMonth() - 1] || ''; + public getLocalizedCalendarMonthDisplayShortName(options: DateTimeFormatOptions): string { + if (!options || !options.localeData) { + return ''; + } + + const names = options.localeData.monthsShort(); + return names[this.getLocalizedCalendarMonth(options) - 1] || ''; } public getGregorianCalendarDay(): number { return this.instance.date(); } - public getLocalizedCalendarDay(): number { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + public getLocalizedCalendarDay(options: DateTimeFormatOptions): number { return this.instance.date(); } @@ -140,18 +175,30 @@ class MomentDateTime implements DateTime { return WeekDay.valueOf(this.instance.day()) as WeekDay; } - public getWeekDayDisplayName(): string { - const names = this.instance.localeData().weekdays(); + public getWeekDayDisplayName(options: DateTimeFormatOptions): string { + if (!options || !options.localeData) { + return ''; + } + + const names = options.localeData.weekdays(); return names[this.instance.day()] || ''; } - public getWeekDayDisplayShortName(): string { - const names = this.instance.localeData().weekdaysShort(); + public getWeekDayDisplayShortName(options: DateTimeFormatOptions): string { + if (!options || !options.localeData) { + return ''; + } + + const names = options.localeData.weekdaysShort(); return names[this.instance.day()] || ''; } - public getWeekDayDisplayMinName(): string { - const names = this.instance.localeData().weekdaysMin(); + public getWeekDayDisplayMinName(options: DateTimeFormatOptions): string { + if (!options || !options.localeData) { + return ''; + } + + const names = options.localeData.weekdaysMin(); return names[this.instance.day()] || ''; } @@ -167,8 +214,12 @@ class MomentDateTime implements DateTime { return this.instance.second(); } - public getDisplayAMPM(): string { - return this.instance.localeData().meridiem(this.getHour(), this.getMinute(), false); + public getDisplayAMPM(options: DateTimeFormatOptions): string { + if (!options || !options.localeData) { + return ''; + } + + return options.localeData.meridiem(this.getHour(), this.getMinute(), false); } public getTimezoneUtcOffsetMinutes(): number { @@ -190,7 +241,7 @@ class MomentDateTime implements DateTime { }; } - public format(format: string): string { + public format(format: string, options: DateTimeFormatOptions): string { let result = ''; let i = 0; @@ -201,7 +252,24 @@ class MomentDateTime implements DateTime { const formatFunc = MomentDateTime.tokenFormatFuncs[token]; if (isFunction(formatFunc)) { - result += formatFunc(this); + const formattedResult: DateTimeFormatResult = formatFunc(this, options); + let formattedValue: string = formattedResult.value.toString(); + + if (isNumber(formattedResult.value)) { + if (isDefined(formattedResult.numeralLength)) { + formattedValue = formattedValue.padStart(formattedResult.numeralLength, '0'); + } + + if (options && options.numeralSystem) { + formattedValue = options.numeralSystem.replaceWesternArabicDigitsToLocalizedDigits(formattedValue); + } + } else if (isString(formattedValue)) { + if (formattedResult.hasNumeral && options && options.numeralSystem) { + formattedValue = options.numeralSystem.replaceWesternArabicDigitsToLocalizedDigits(formattedValue); + } + } + + result += formattedValue; i += len; matched = true; break; @@ -405,20 +473,20 @@ export function parseDateTimeFromUnixTime(unixTime: number, utcOffset?: number, return MomentDateTime.of(moment.unix(unixTime)); } -export function formatUnixTime(unixTime: number, format: string, utcOffset?: number, currentUtcOffset?: number): string { - return parseDateTimeFromUnixTime(unixTime, utcOffset, currentUtcOffset).format(format); +export function formatUnixTime(unixTime: number, format: string, options: DateTimeFormatOptions, utcOffset?: number, currentUtcOffset?: number): string { + return parseDateTimeFromUnixTime(unixTime, utcOffset, currentUtcOffset).format(format, options); } -export function formatCurrentTime(format: string): string { - return MomentDateTime.now().format(format); +export function formatCurrentTime(format: string, options: DateTimeFormatOptions): string { + return MomentDateTime.now().format(format, options); } -export function formatGregorianCalendarYearDashMonthDashDay(date: TextualYearMonthDay, format: string): string { - return MomentDateTime.of(moment(date, 'YYYY-MM-DD')).format(format); +export function formatGregorianCalendarYearDashMonthDashDay(date: TextualYearMonthDay, format: string, options: DateTimeFormatOptions): string { + return MomentDateTime.of(moment(date, 'YYYY-MM-DD')).format(format, options); } -export function formatGregorianCalendarMonthDashDay(monthDay: TextualYearMonth, format: string): string { - return MomentDateTime.of(moment(monthDay, 'MM-DD')).format(format); +export function formatGregorianCalendarMonthDashDay(monthDay: TextualYearMonth, format: string, options: DateTimeFormatOptions): string { + return MomentDateTime.of(moment(monthDay, 'MM-DD')).format(format, options); } export function getGregorianCalendarYearAndMonthFromUnixTime(unixTime: number): TextualYearMonth | '' { diff --git a/src/locales/de.json b/src/locales/de.json index 6b3b1fb6..ec9da47c 100644 --- a/src/locales/de.json +++ b/src/locales/de.json @@ -22,6 +22,8 @@ "currency": "EUR", "firstDayOfWeek": "Monday", "fiscalYearFormat": "EndYYYY", + "calendarDisplayType": "Gregorian", + "dateDisplayType": "Gregorian", "longDateFormat": "DDMMYYYY", "shortDateFormat": "DDMMYYYY", "longTimeFormat": "HHMMSS", @@ -73,6 +75,11 @@ "mm_dd_yyyy": "MM/DD", "dd_mm_yyyy": "DD.MM" }, + "shortDay": { + "yyyy_mm_dd": "DD", + "mm_dd_yyyy": "DD", + "dd_mm_yyyy": "DD" + }, "longTime": { "hh_mm_ss": "HH:mm:ss", "a_hh_mm_ss": "A hh:mm:ss", @@ -129,6 +136,11 @@ "defaultImportDataMappingFileName": "ezBookkeeping_import_data_mapping", "defaultImportReplaceRuleFileName": "ezBookkeeping_import_replace_rule" }, + "calendar": { + "Gregorian": "Gregorian", + "Buddhist": "Buddhist", + "Gregorian (with Chinese Calendar)": "Gregorian (with Chinese Calendar)" + }, "datetime": { "AM": { "content": "AM" @@ -1498,6 +1510,8 @@ "Default Account": "Standardkonto", "First Day of Week": "Erster Wochentag", "Fiscal Year Start Date": "Fiscal Year Start Date", + "Calendar Display Type": "Calendar Display Type", + "Date Display Type": "Date Display Type", "Long Date Format": "Langes Datumsformat", "Short Date Format": "Kurzes Datumsformat", "Long Time Format": "Langes Zeitformat", diff --git a/src/locales/en.json b/src/locales/en.json index e8dd81ff..d172d25f 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -22,6 +22,8 @@ "currency": "USD", "firstDayOfWeek": "Sunday", "fiscalYearFormat": "EndYYYY", + "calendarDisplayType": "Gregorian", + "dateDisplayType": "Gregorian", "longDateFormat": "MMDDYYYY", "shortDateFormat": "MMDDYYYY", "longTimeFormat": "HHMMSSA", @@ -73,6 +75,11 @@ "mm_dd_yyyy": "M/D", "dd_mm_yyyy": "D/M" }, + "shortDay": { + "yyyy_mm_dd": "D", + "mm_dd_yyyy": "D", + "dd_mm_yyyy": "D" + }, "longTime": { "hh_mm_ss": "HH:mm:ss", "a_hh_mm_ss": "A hh:mm:ss", @@ -129,6 +136,11 @@ "defaultImportDataMappingFileName": "ezBookkeeping_import_data_mapping", "defaultImportReplaceRuleFileName": "ezBookkeeping_import_replace_rule" }, + "calendar": { + "Gregorian": "Gregorian", + "Buddhist": "Buddhist", + "Gregorian (with Chinese Calendar)": "Gregorian (with Chinese Calendar)" + }, "datetime": { "AM": { "content": "AM" @@ -1498,6 +1510,8 @@ "Default Account": "Default Account", "First Day of Week": "First Day of Week", "Fiscal Year Start Date": "Fiscal Year Start Date", + "Calendar Display Type": "Calendar Display Type", + "Date Display Type": "Date Display Type", "Long Date Format": "Long Date Format", "Short Date Format": "Short Date Format", "Long Time Format": "Long Time Format", diff --git a/src/locales/es.json b/src/locales/es.json index 4f1502fd..94afd669 100644 --- a/src/locales/es.json +++ b/src/locales/es.json @@ -22,6 +22,8 @@ "currency": "EUR", "firstDayOfWeek": "Monday", "fiscalYearFormat": "EndYYYY", + "calendarDisplayType": "Gregorian", + "dateDisplayType": "Gregorian", "longDateFormat": "DDMMYYYY", "shortDateFormat": "DDMMYYYY", "longTimeFormat": "HHMMSS", @@ -73,6 +75,11 @@ "mm_dd_yyyy": "MM/DD", "dd_mm_yyyy": "DD/MM" }, + "shortDay": { + "yyyy_mm_dd": "DD", + "mm_dd_yyyy": "DD", + "dd_mm_yyyy": "DD" + }, "longTime": { "hh_mm_ss": "H:mm:ss", "a_hh_mm_ss": "A h:mm:ss", @@ -129,6 +136,11 @@ "defaultImportDataMappingFileName": "ezBookkeeping_import_data_mapping", "defaultImportReplaceRuleFileName": "ezBookkeeping_import_replace_rule" }, + "calendar": { + "Gregorian": "Gregorian", + "Buddhist": "Buddhist", + "Gregorian (with Chinese Calendar)": "Gregorian (with Chinese Calendar)" + }, "datetime": { "AM": { "content": "AM" @@ -1498,6 +1510,8 @@ "Default Account": "Cuenta predeterminada", "First Day of Week": "Primer día de la semana", "Fiscal Year Start Date": "Fiscal Year Start Date", + "Calendar Display Type": "Calendar Display Type", + "Date Display Type": "Date Display Type", "Long Date Format": "Formato largo de fecha", "Short Date Format": "Formato corto de fecha", "Long Time Format": "Formato largo de hora", diff --git a/src/locales/helpers.ts b/src/locales/helpers.ts index 358810de..835dff5d 100644 --- a/src/locales/helpers.ts +++ b/src/locales/helpers.ts @@ -16,6 +16,14 @@ import { } from '@/core/text.ts'; import { + CalendarType, + CalendarDisplayType, + DateDisplayType +} from '@/core/calendar.ts'; + +import { + type DateTimeFormatOptions, + type DateTimeLocaleData, type TextualYearMonth, type TextualYearMonthDay, type DateFormat, @@ -28,6 +36,7 @@ import { Month, WeekDay, MeridiemIndicator, + KnownDateTimeFormat, LongDateFormat, ShortDateFormat, LongTimeFormat, @@ -439,6 +448,10 @@ export function useI18n() { return localizedParameters; } + function getDateTimeLocaleData(): DateTimeLocaleData { + return moment.localeData(); + } + function getAllCurrencyDisplayTypes(numeralSystem: NumeralSystem, decimalSeparator: string): TypeAndDisplayName[] { const defaultCurrencyDisplayTypeName = t('default.currencyDisplayType'); let defaultCurrencyDisplayType = CurrencyDisplayType.parse(defaultCurrencyDisplayTypeName); @@ -473,6 +486,32 @@ export function useI18n() { return ret; } + function getAllLocalizedCalendarTypes(allTypeAndNameArray: CalendarDisplayType[] | DateDisplayType[], localeDefaultType: CalendarDisplayType | DateDisplayType | undefined, systemDefaultType: CalendarDisplayType | DateDisplayType, languageDefaultValue: number): TypeAndDisplayName[] { + let defaultType: TypeAndName | undefined = localeDefaultType; + + if (!defaultType) { + defaultType = systemDefaultType; + } + + const ret: TypeAndDisplayName[] = []; + + ret.push({ + type: languageDefaultValue, + displayName: `${t('Language Default')} (${t('calendar.' + defaultType.name)})` + }); + + for (let i = 0; i < allTypeAndNameArray.length; i++) { + const type = allTypeAndNameArray[i]; + + ret.push({ + type: type.type, + displayName: t('calendar.' + type.name) + }); + } + + return ret; + } + function getLocalizedDisplayNameAndType(typeAndNames: TypeAndName[]): TypeAndDisplayName[] { const ret: TypeAndDisplayName[] = []; @@ -617,6 +656,10 @@ export function useI18n() { return getLocalizedDateTimeFormat('shortMonthDay', ShortDateFormat.all(), ShortDateFormat.values(), userStore.currentUserShortDateFormat, 'shortDateFormat', ShortDateFormat.Default); } + function getLocalizedShortDayFormat(): string { + return getLocalizedDateTimeFormat('shortDay', ShortDateFormat.all(), ShortDateFormat.values(), userStore.currentUserShortDateFormat, 'shortDateFormat', ShortDateFormat.Default); + } + function getLocalizedLongTimeFormat(): string { return getLocalizedDateTimeFormat('longTime', LongTimeFormat.all(), LongTimeFormat.values(), userStore.currentUserLongTimeFormat, 'longTimeFormat', LongTimeFormat.Default); } @@ -625,6 +668,25 @@ export function useI18n() { return getLocalizedDateTimeFormat('shortTime', ShortTimeFormat.all(), ShortTimeFormat.values(), userStore.currentUserShortTimeFormat, 'shortTimeFormat', ShortTimeFormat.Default); } + function getDateTimeFormatOptions(options?: { calendarType?: CalendarType, numeralSystem?: NumeralSystem }): DateTimeFormatOptions { + let calendarType: CalendarType | undefined = options?.calendarType; + let numeralSystem: NumeralSystem | undefined = options?.numeralSystem; + + if (!isDefined(calendarType)) { + calendarType = getCurrentDateDisplayType().calendarType; + } + + if (!isDefined(numeralSystem)) { + numeralSystem = getCurrentNumeralSystemType(); + } + + return { + calendarType: calendarType, + numeralSystem: numeralSystem, + localeData: getDateTimeLocaleData() + }; + } + function getNumberFormatOptions({numeralSystem, digitGrouping, decimalSeparator, currencyCode}: { numeralSystem?: NumeralSystem, digitGrouping?: DigitGroupingType, @@ -904,14 +966,15 @@ export function useI18n() { return ret; } - function getLocalizedDateTimeFormats(type: string, allFormatMap: Record, allFormatArray: T[], languageDefaultTypeNameKey: string, systemDefaultFormatType: T): LocalizedDateTimeFormat[] { + function getLocalizedDateTimeFormats(type: string, allFormatMap: Record, allFormatArray: T[], languageDefaultTypeNameKey: string, systemDefaultFormatType: T, calendarType?: CalendarType): LocalizedDateTimeFormat[] { const defaultFormat = getLocalizedDateTimeFormat(type, allFormatMap, allFormatArray, LANGUAGE_DEFAULT_DATE_TIME_FORMAT_VALUE, languageDefaultTypeNameKey, systemDefaultFormatType); const ret: LocalizedDateTimeFormat[] = []; + const dateTimeFormatOptions = getDateTimeFormatOptions({ calendarType: calendarType }); ret.push({ type: LANGUAGE_DEFAULT_DATE_TIME_FORMAT_VALUE, format: defaultFormat, - displayName: `${t('Language Default')} (${formatCurrentTime(defaultFormat)})` + displayName: `${t('Language Default')} (${formatCurrentTime(defaultFormat, dateTimeFormatOptions)})` }); for (let i = 0; i < allFormatArray.length; i++) { @@ -921,7 +984,7 @@ export function useI18n() { ret.push({ type: formatType.type, format: format, - displayName: formatCurrentTime(format) + displayName: formatCurrentTime(format, dateTimeFormatOptions) }); } @@ -968,6 +1031,7 @@ export function useI18n() { function getAllRecentMonthDateRanges(includeAll: boolean, includeCustom: boolean): LocalizedRecentMonthDateRange[] { const allRecentMonthDateRanges: LocalizedRecentMonthDateRange[] = []; const recentDateRanges = getRecentMonthDateRanges(12); + const dateTimeFormatOptions = getDateTimeFormatOptions(); if (includeAll) { allRecentMonthDateRanges.push({ @@ -988,7 +1052,7 @@ export function useI18n() { year: recentDateRange.year, month: recentDateRange.month, isPreset: true, - displayName: formatUnixTime(recentDateRange.minTime, getLocalizedLongYearMonthFormat()) + displayName: formatUnixTime(recentDateRange.minTime, getLocalizedLongYearMonthFormat(), dateTimeFormatOptions) }); } @@ -1498,6 +1562,36 @@ export function useI18n() { return numeralSystem.getAllDigits(); } + function getCurrentCalendarDisplayType(): CalendarDisplayType { + let calendarDisplayType = CalendarDisplayType.valueOf(userStore.currentUserCalendarDisplayType); + + if (!calendarDisplayType) { + const defaultCalendarDisplayTypeName = t('default.calendarDisplayType'); + calendarDisplayType = CalendarDisplayType.parse(defaultCalendarDisplayTypeName); + + if (!calendarDisplayType) { + calendarDisplayType = CalendarDisplayType.Default; + } + } + + return calendarDisplayType; + } + + function getCurrentDateDisplayType(): DateDisplayType { + let dateDisplayType = DateDisplayType.valueOf(userStore.currentUserDateDisplayType); + + if (!dateDisplayType) { + const defaultDateDisplayTypeName = t('default.dateDisplayType'); + dateDisplayType = DateDisplayType.parse(defaultDateDisplayTypeName); + + if (!dateDisplayType) { + dateDisplayType = DateDisplayType.Default; + } + } + + return dateDisplayType; + } + function getCurrentNumeralSystemType(): NumeralSystem { let numeralSystemType = NumeralSystem.valueOf(userStore.currentUserNumeralSystem); @@ -1619,17 +1713,18 @@ export function useI18n() { } function formatGregorianCalendarYearDashMonthDashDayToLongDate(date: TextualYearMonthDay): string { - return formatGregorianCalendarYearDashMonthDashDay(date, getLocalizedLongDateFormat()); + return formatGregorianCalendarYearDashMonthDashDay(date, getLocalizedLongDateFormat(), getDateTimeFormatOptions()); } function formatGregorianCalendarMonthDashDayToLongMonthDay(monthDay: TextualYearMonth): string { - return formatGregorianCalendarMonthDashDay(monthDay, getLocalizedLongMonthDayFormat()); + return formatGregorianCalendarMonthDashDay(monthDay, getLocalizedLongMonthDayFormat(), getDateTimeFormatOptions()); } function formatUnixTimeToYearQuarter(unixTime: number): string { + const dateTimeFormatOptions = getDateTimeFormatOptions(); const date = parseDateTimeFromUnixTime(unixTime); - const year = date.getLocalizedCalendarYear(); - const quarter = date.getLocalizedCalendarQuarter(); + const year = date.getLocalizedCalendarYear(dateTimeFormatOptions); + const quarter = date.getLocalizedCalendarQuarter(dateTimeFormatOptions); return formatYearQuarter(year, quarter); } @@ -1650,6 +1745,7 @@ export function useI18n() { } const allDateRanges = DateRange.values(); + const dateTimeFormatOptions = getDateTimeFormatOptions(); for (let i = 0; i < allDateRanges.length; i++) { const dateRange = allDateRanges[i]; @@ -1661,31 +1757,31 @@ export function useI18n() { if (isDateRangeMatchFullYears(startTime, endTime)) { const format = getLocalizedShortYearFormat(); - const displayStartTime = formatUnixTime(startTime, format); - const displayEndTime = formatUnixTime(endTime, format); + const displayStartTime = formatUnixTime(startTime, format, dateTimeFormatOptions); + const displayEndTime = formatUnixTime(endTime, format, dateTimeFormatOptions); return displayStartTime !== displayEndTime ? `${displayStartTime} ~ ${displayEndTime}` : displayStartTime; } if (isDateRangeMatchFullMonths(startTime, endTime)) { const format = getLocalizedShortYearMonthFormat(); - const displayStartTime = formatUnixTime(startTime, format); - const displayEndTime = formatUnixTime(endTime, format); + const displayStartTime = formatUnixTime(startTime, format, dateTimeFormatOptions); + const displayEndTime = formatUnixTime(endTime, format, dateTimeFormatOptions); return displayStartTime !== displayEndTime ? `${displayStartTime} ~ ${displayEndTime}` : displayStartTime; } - const startTimeYear = parseDateTimeFromUnixTime(startTime).getLocalizedCalendarYear(); - const endTimeYear = parseDateTimeFromUnixTime(endTime).getLocalizedCalendarYear(); + const startTimeYear = parseDateTimeFromUnixTime(startTime).getLocalizedCalendarYear(dateTimeFormatOptions); + const endTimeYear = parseDateTimeFromUnixTime(endTime).getLocalizedCalendarYear(dateTimeFormatOptions); const format = getLocalizedShortDateFormat(); - const displayStartTime = formatUnixTime(startTime, format); - const displayEndTime = formatUnixTime(endTime, format); + const displayStartTime = formatUnixTime(startTime, format, dateTimeFormatOptions); + const displayEndTime = formatUnixTime(endTime, format, dateTimeFormatOptions); if (displayStartTime === displayEndTime) { return displayStartTime; } else if (startTimeYear === endTimeYear) { - const displayShortEndTime = formatUnixTime(endTime, getLocalizedShortMonthDayFormat()); + const displayShortEndTime = formatUnixTime(endTime, getLocalizedShortMonthDayFormat(), dateTimeFormatOptions); return `${displayStartTime} ~ ${displayShortEndTime}`; } @@ -1697,11 +1793,13 @@ export function useI18n() { format = FiscalYearFormat.Default; } + const dateTimeFormatOptions = getDateTimeFormatOptions(); + return t('format.fiscalYear.' + format.typeName, { - StartYYYY: formatUnixTime(timeRange.minUnixTime, 'YYYY'), - StartYY: formatUnixTime(timeRange.minUnixTime, 'YY'), - EndYYYY: formatUnixTime(timeRange.maxUnixTime, 'YYYY'), - EndYY: formatUnixTime(timeRange.maxUnixTime, 'YY'), + StartYYYY: formatUnixTime(timeRange.minUnixTime, 'YYYY', dateTimeFormatOptions), + StartYY: formatUnixTime(timeRange.minUnixTime, 'YY', dateTimeFormatOptions), + EndYYYY: formatUnixTime(timeRange.maxUnixTime, 'YYYY', dateTimeFormatOptions), + EndYY: formatUnixTime(timeRange.maxUnixTime, 'YY', dateTimeFormatOptions), }); } @@ -2093,10 +2191,12 @@ export function useI18n() { getAllShortWeekdayNames, getAllMinWeekdayNames, getAllWeekDays, - getAllLongDateFormats: () => getLocalizedDateTimeFormats('longDate', LongDateFormat.all(), LongDateFormat.values(), 'longDateFormat', LongDateFormat.Default), - getAllShortDateFormats: () => getLocalizedDateTimeFormats('shortDate', ShortDateFormat.all(), ShortDateFormat.values(), 'shortDateFormat', ShortDateFormat.Default), - getAllLongTimeFormats: () => getLocalizedDateTimeFormats('longTime', LongTimeFormat.all(), LongTimeFormat.values(), 'longTimeFormat', LongTimeFormat.Default), - getAllShortTimeFormats: () => getLocalizedDateTimeFormats('shortTime', ShortTimeFormat.all(), ShortTimeFormat.values(), 'shortTimeFormat', ShortTimeFormat.Default), + getAllCalendarDisplayTypes: () => getAllLocalizedCalendarTypes(CalendarDisplayType.values(), CalendarDisplayType.parse(t('default.calendarDisplayType')), CalendarDisplayType.Default, CalendarDisplayType.LanguageDefaultType), + getAllDateDisplayTypes: () => getAllLocalizedCalendarTypes(DateDisplayType.values(), DateDisplayType.parse(t('default.dateDisplayType')), DateDisplayType.Default, DateDisplayType.LanguageDefaultType), + getAllLongDateFormats: (calendarType?: CalendarType) => getLocalizedDateTimeFormats('longDate', LongDateFormat.all(), LongDateFormat.values(), 'longDateFormat', LongDateFormat.Default, calendarType), + getAllShortDateFormats: (calendarType?: CalendarType) => getLocalizedDateTimeFormats('shortDate', ShortDateFormat.all(), ShortDateFormat.values(), 'shortDateFormat', ShortDateFormat.Default, calendarType), + getAllLongTimeFormats: (calendarType?: CalendarType) => getLocalizedDateTimeFormats('longTime', LongTimeFormat.all(), LongTimeFormat.values(), 'longTimeFormat', LongTimeFormat.Default, calendarType), + getAllShortTimeFormats: (calendarType?: CalendarType) => getLocalizedDateTimeFormats('shortTime', ShortTimeFormat.all(), ShortTimeFormat.values(), 'shortTimeFormat', ShortTimeFormat.Default, calendarType), getAllFiscalYearFormats, getAllDateRanges, getAllRecentMonthDateRanges, @@ -2138,11 +2238,13 @@ export function useI18n() { getMultiMonthdayShortNames, getMultiWeekdayLongNames, getAllLocalizedDigits, - getCurrentFiscalYearFormatType, + getCurrentCalendarDisplayType, + getCurrentDateDisplayType, getCurrentNumeralSystemType, getCurrentDecimalSeparator, getCurrentDigitGroupingSymbol, getCurrentDigitGroupingType, + getCurrentFiscalYearFormatType, getCurrencyName, isLongDateMonthAfterYear, isShortDateMonthAfterYear, @@ -2154,20 +2256,22 @@ export function useI18n() { isLongTimeMinuteTwoDigits, isLongTimeSecondTwoDigits, // format functions - formatUnixTimeToLongDateTime: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedLongDateFormat() + ' ' + getLocalizedLongTimeFormat(), utcOffset, currentUtcOffset), - formatUnixTimeToShortDateTime: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedShortDateFormat() + ' ' + getLocalizedShortTimeFormat(), utcOffset, currentUtcOffset), - formatUnixTimeToLongDate: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedLongDateFormat(), utcOffset, currentUtcOffset), - formatUnixTimeToShortDate: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedShortDateFormat(), utcOffset, currentUtcOffset), - formatUnixTimeToLongYear: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedLongYearFormat(), utcOffset, currentUtcOffset), - formatUnixTimeToShortYear: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedShortYearFormat(), utcOffset, currentUtcOffset), - formatUnixTimeToLongMonth: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, 'MMMM', utcOffset, currentUtcOffset), - formatUnixTimeToShortMonth: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, 'MMM', utcOffset, currentUtcOffset), - formatUnixTimeToLongYearMonth: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedLongYearMonthFormat(), utcOffset, currentUtcOffset), - formatUnixTimeToShortYearMonth: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedShortYearMonthFormat(), utcOffset, currentUtcOffset), - formatUnixTimeToLongMonthDay: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedLongMonthDayFormat(), utcOffset, currentUtcOffset), - formatUnixTimeToShortMonthDay: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedShortMonthDayFormat(), utcOffset, currentUtcOffset), - formatUnixTimeToLongTime: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedLongTimeFormat(), utcOffset, currentUtcOffset), - formatUnixTimeToShortTime: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedShortTimeFormat(), utcOffset, currentUtcOffset), + formatUnixTimeToDefaultDateTimeWithoutLocaleOptions: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, KnownDateTimeFormat.DefaultDateTime.format, getDateTimeFormatOptions({ calendarType: CalendarType.Gregorian, numeralSystem: NumeralSystem.WesternArabicNumerals }), utcOffset, currentUtcOffset), + 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), + formatUnixTimeToLongYear: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedLongYearFormat(), getDateTimeFormatOptions(), utcOffset, currentUtcOffset), + formatUnixTimeToShortYear: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedShortYearFormat(), getDateTimeFormatOptions(), utcOffset, currentUtcOffset), + formatUnixTimeToLongMonth: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, 'MMMM', getDateTimeFormatOptions(), utcOffset, currentUtcOffset), + formatUnixTimeToShortMonth: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, 'MMM', getDateTimeFormatOptions(), utcOffset, currentUtcOffset), + formatUnixTimeToLongYearMonth: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedLongYearMonthFormat(), getDateTimeFormatOptions(), utcOffset, currentUtcOffset), + formatUnixTimeToShortYearMonth: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedShortYearMonthFormat(), 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), + formatUnixTimeToDayOfMonth: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedShortDayFormat(), getDateTimeFormatOptions(), utcOffset, currentUtcOffset), formatGregorianCalendarYearDashMonthDashDayToLongDate, formatGregorianCalendarMonthDashDayToLongMonthDay, formatUnixTimeToYearQuarter, diff --git a/src/locales/it.json b/src/locales/it.json index 6bfcb31e..03e63fe5 100644 --- a/src/locales/it.json +++ b/src/locales/it.json @@ -22,6 +22,8 @@ "currency": "EUR", "firstDayOfWeek": "Monday", "fiscalYearFormat": "EndYYYY", + "calendarDisplayType": "Gregorian", + "dateDisplayType": "Gregorian", "longDateFormat": "DDMMYYYY", "shortDateFormat": "DDMMYYYY", "longTimeFormat": "HHMMSS", @@ -73,6 +75,11 @@ "mm_dd_yyyy": "MM/DD", "dd_mm_yyyy": "DD/MM" }, + "shortDay": { + "yyyy_mm_dd": "DD", + "mm_dd_yyyy": "DD", + "dd_mm_yyyy": "DD" + }, "longTime": { "hh_mm_ss": "HH:mm:ss", "a_hh_mm_ss": "A hh:mm:ss", @@ -129,6 +136,11 @@ "defaultImportDataMappingFileName": "ezBookkeeping_import_data_mapping", "defaultImportReplaceRuleFileName": "ezBookkeeping_import_replace_rule" }, + "calendar": { + "Gregorian": "Gregorian", + "Buddhist": "Buddhist", + "Gregorian (with Chinese Calendar)": "Gregorian (with Chinese Calendar)" + }, "datetime": { "AM": { "content": "AM" @@ -1498,6 +1510,8 @@ "Default Account": "Account predefinito", "First Day of Week": "Primo giorno della settimana", "Fiscal Year Start Date": "Fiscal Year Start Date", + "Calendar Display Type": "Calendar Display Type", + "Date Display Type": "Date Display Type", "Long Date Format": "Formato data lungo", "Short Date Format": "Formato data breve", "Long Time Format": "Formato ora lungo", diff --git a/src/locales/ja.json b/src/locales/ja.json index 39aca0dd..9357c69c 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -22,6 +22,8 @@ "currency": "JPY", "firstDayOfWeek": "Sunday", "fiscalYearFormat": "EndYYYY", + "calendarDisplayType": "Gregorian", + "dateDisplayType": "Gregorian", "longDateFormat": "YYYYMMDD", "shortDateFormat": "YYYYMMDD", "longTimeFormat": "HHMMSS", @@ -73,6 +75,11 @@ "mm_dd_yyyy": "M/D", "dd_mm_yyyy": "D/M" }, + "shortDay": { + "yyyy_mm_dd": "D", + "mm_dd_yyyy": "D", + "dd_mm_yyyy": "D" + }, "longTime": { "hh_mm_ss": "HH:mm:ss", "a_hh_mm_ss": "A hh:mm:ss", @@ -129,6 +136,11 @@ "defaultImportDataMappingFileName": "ezBookkeeping_import_data_mapping", "defaultImportReplaceRuleFileName": "ezBookkeeping_import_replace_rule" }, + "calendar": { + "Gregorian": "Gregorian", + "Buddhist": "Buddhist", + "Gregorian (with Chinese Calendar)": "Gregorian (with Chinese Calendar)" + }, "datetime": { "AM": { "content": "午前" @@ -1498,6 +1510,8 @@ "Default Account": "デフォルト口座", "First Day of Week": "週の最初の曜日", "Fiscal Year Start Date": "Fiscal Year Start Date", + "Calendar Display Type": "Calendar Display Type", + "Date Display Type": "Date Display Type", "Long Date Format": "長い日付形式", "Short Date Format": "短い日付形式", "Long Time Format": "長い時間形式", diff --git a/src/locales/nl.json b/src/locales/nl.json index 8357cede..6410ac89 100644 --- a/src/locales/nl.json +++ b/src/locales/nl.json @@ -22,6 +22,8 @@ "currency": "EUR", "firstDayOfWeek": "Monday", "fiscalYearFormat": "EndYYYY", + "calendarDisplayType": "Gregorian", + "dateDisplayType": "Gregorian", "longDateFormat": "DDMMYYYY", "shortDateFormat": "DDMMYYYY", "longTimeFormat": "HHMMSS", @@ -73,6 +75,11 @@ "mm_dd_yyyy": "M/D", "dd_mm_yyyy": "D/M" }, + "shortDay": { + "yyyy_mm_dd": "D", + "mm_dd_yyyy": "D", + "dd_mm_yyyy": "D" + }, "longTime": { "hh_mm_ss": "HH:mm:ss", "a_hh_mm_ss": "A hh:mm:ss", @@ -129,6 +136,11 @@ "defaultImportDataMappingFileName": "ezBookkeeping_import_data_mapping", "defaultImportReplaceRuleFileName": "ezBookkeeping_import_replace_rule" }, + "calendar": { + "Gregorian": "Gregorian", + "Buddhist": "Buddhist", + "Gregorian (with Chinese Calendar)": "Gregorian (with Chinese Calendar)" + }, "datetime": { "AM": { "content": "AM" @@ -1498,6 +1510,8 @@ "Default Account": "Standaardrekening", "First Day of Week": "Eerste dag van de week", "Fiscal Year Start Date": "Startdatum boekjaar", + "Calendar Display Type": "Calendar Display Type", + "Date Display Type": "Date Display Type", "Long Date Format": "Lang datumformaat", "Short Date Format": "Kort datumformaat", "Long Time Format": "Lang tijdsformaat", diff --git a/src/locales/pt_BR.json b/src/locales/pt_BR.json index a000f375..1bccbca1 100644 --- a/src/locales/pt_BR.json +++ b/src/locales/pt_BR.json @@ -22,6 +22,8 @@ "currency": "BRL", "firstDayOfWeek": "Monday", "fiscalYearFormat": "EndYYYY", + "calendarDisplayType": "Gregorian", + "dateDisplayType": "Gregorian", "longDateFormat": "DDMMYYYY", "shortDateFormat": "DDMMYYYY", "longTimeFormat": "HHMMSS", @@ -73,6 +75,11 @@ "mm_dd_yyyy": "MM/DD", "dd_mm_yyyy": "DD/MM" }, + "shortDay": { + "yyyy_mm_dd": "DD", + "mm_dd_yyyy": "DD", + "dd_mm_yyyy": "DD" + }, "longTime": { "hh_mm_ss": "HH:mm:ss", "a_hh_mm_ss": "A hh:mm:ss", @@ -129,6 +136,11 @@ "defaultImportDataMappingFileName": "ezBookkeeping_import_data_mapping", "defaultImportReplaceRuleFileName": "ezBookkeeping_import_replace_rule" }, + "calendar": { + "Gregorian": "Gregorian", + "Buddhist": "Buddhist", + "Gregorian (with Chinese Calendar)": "Gregorian (with Chinese Calendar)" + }, "datetime": { "AM": { "content": "AM" @@ -1498,6 +1510,8 @@ "Default Account": "Conta Padrão", "First Day of Week": "Primeiro Dia da Semana", "Fiscal Year Start Date": "Data de Início do Ano Fiscal", + "Calendar Display Type": "Calendar Display Type", + "Date Display Type": "Date Display Type", "Long Date Format": "Formato de Data Longa", "Short Date Format": "Formato de Data Curta", "Long Time Format": "Formato de Hora Longa", diff --git a/src/locales/ru.json b/src/locales/ru.json index f61ce0a6..7fb30b0e 100644 --- a/src/locales/ru.json +++ b/src/locales/ru.json @@ -22,6 +22,8 @@ "currency": "RUB", "firstDayOfWeek": "Monday", "fiscalYearFormat": "EndYYYY", + "calendarDisplayType": "Gregorian", + "dateDisplayType": "Gregorian", "longDateFormat": "DDMMYYYY", "shortDateFormat": "DDMMYYYY", "longTimeFormat": "HHMMSS", @@ -73,6 +75,11 @@ "mm_dd_yyyy": "MM/DD", "dd_mm_yyyy": "DD.MM" }, + "shortDay": { + "yyyy_mm_dd": "DD", + "mm_dd_yyyy": "DD", + "dd_mm_yyyy": "DD" + }, "longTime": { "hh_mm_ss": "H:mm:ss", "a_hh_mm_ss": "A h:mm:ss", @@ -129,6 +136,11 @@ "defaultImportDataMappingFileName": "ezBookkeeping_import_data_mapping", "defaultImportReplaceRuleFileName": "ezBookkeeping_import_replace_rule" }, + "calendar": { + "Gregorian": "Gregorian", + "Buddhist": "Buddhist", + "Gregorian (with Chinese Calendar)": "Gregorian (with Chinese Calendar)" + }, "datetime": { "AM": { "content": "ДП" @@ -1498,6 +1510,8 @@ "Default Account": "Счет по умолчанию", "First Day of Week": "Первый день недели", "Fiscal Year Start Date": "Fiscal Year Start Date", + "Calendar Display Type": "Calendar Display Type", + "Date Display Type": "Date Display Type", "Long Date Format": "Длинный формат даты", "Short Date Format": "Короткий формат даты", "Long Time Format": "Длинный формат времени", diff --git a/src/locales/uk.json b/src/locales/uk.json index 55b39bf4..f3b55500 100644 --- a/src/locales/uk.json +++ b/src/locales/uk.json @@ -22,6 +22,8 @@ "currency": "UAH", "firstDayOfWeek": "Monday", "fiscalYearFormat": "EndYYYY", + "calendarDisplayType": "Gregorian", + "dateDisplayType": "Gregorian", "longDateFormat": "DDMMYYYY", "shortDateFormat": "DDMMYYYY", "longTimeFormat": "HHMMSS", @@ -73,6 +75,11 @@ "mm_dd_yyyy": "MM/DD", "dd_mm_yyyy": "DD.MM" }, + "shortDay": { + "yyyy_mm_dd": "DD", + "mm_dd_yyyy": "DD", + "dd_mm_yyyy": "DD" + }, "longTime": { "hh_mm_ss": "HH:mm:ss", "a_hh_mm_ss": "A hh:mm:ss", @@ -129,6 +136,11 @@ "defaultImportDataMappingFileName": "ezBookkeeping_import_data_mapping", "defaultImportReplaceRuleFileName": "ezBookkeeping_import_replace_rule" }, + "calendar": { + "Gregorian": "Gregorian", + "Buddhist": "Buddhist", + "Gregorian (with Chinese Calendar)": "Gregorian (with Chinese Calendar)" + }, "datetime": { "AM": { "content": "ДП" @@ -1498,6 +1510,8 @@ "Default Account": "Рахунок за замовчуванням", "First Day of Week": "Перший день тижня", "Fiscal Year Start Date": "Fiscal Year Start Date", + "Calendar Display Type": "Calendar Display Type", + "Date Display Type": "Date Display Type", "Long Date Format": "Довгий формат дати", "Short Date Format": "Короткий формат дати", "Long Time Format": "Довгий формат часу", diff --git a/src/locales/vi.json b/src/locales/vi.json index 3baba460..2c194e74 100644 --- a/src/locales/vi.json +++ b/src/locales/vi.json @@ -22,6 +22,8 @@ "currency": "VND", "firstDayOfWeek": "Monday", "fiscalYearFormat": "EndYYYY", + "calendarDisplayType": "Gregorian", + "dateDisplayType": "Gregorian", "longDateFormat": "DDMMYYYY", "shortDateFormat": "DDMMYYYY", "longTimeFormat": "HHMMSSA", @@ -73,6 +75,11 @@ "mm_dd_yyyy": "MM/DD", "dd_mm_yyyy": "DD/MM" }, + "shortDay": { + "yyyy_mm_dd": "DD", + "mm_dd_yyyy": "DD", + "dd_mm_yyyy": "DD" + }, "longTime": { "hh_mm_ss": "HH:mm:ss", "a_hh_mm_ss": "A hh:mm:ss", @@ -129,6 +136,11 @@ "defaultImportDataMappingFileName": "ezBookkeeping_import_data_mapping", "defaultImportReplaceRuleFileName": "ezBookkeeping_import_replace_rule" }, + "calendar": { + "Gregorian": "Gregorian", + "Buddhist": "Buddhist", + "Gregorian (with Chinese Calendar)": "Gregorian (with Chinese Calendar)" + }, "datetime": { "AM": { "content": "SA" @@ -1498,6 +1510,8 @@ "Default Account": "Tài khoản mặc định", "First Day of Week": "Ngày đầu tiên của tuần", "Fiscal Year Start Date": "Fiscal Year Start Date", + "Calendar Display Type": "Calendar Display Type", + "Date Display Type": "Date Display Type", "Long Date Format": "Định dạng ngày dài", "Short Date Format": "Định dạng ngày ngắn", "Long Time Format": "Định dạng thời gian dài", diff --git a/src/locales/zh_Hans.json b/src/locales/zh_Hans.json index 1a8b572e..7f1b14c8 100644 --- a/src/locales/zh_Hans.json +++ b/src/locales/zh_Hans.json @@ -22,6 +22,8 @@ "currency": "CNY", "firstDayOfWeek": "Monday", "fiscalYearFormat": "EndYYYY", + "calendarDisplayType": "Gregorian", + "dateDisplayType": "Gregorian", "longDateFormat": "YYYYMMDD", "shortDateFormat": "YYYYMMDD", "longTimeFormat": "HHMMSS", @@ -73,6 +75,11 @@ "mm_dd_yyyy": "M/D", "dd_mm_yyyy": "D/M" }, + "shortDay": { + "yyyy_mm_dd": "D", + "mm_dd_yyyy": "D", + "dd_mm_yyyy": "D" + }, "longTime": { "hh_mm_ss": "HH:mm:ss", "a_hh_mm_ss": "A hh:mm:ss", @@ -129,6 +136,11 @@ "defaultImportDataMappingFileName": "ezBookkeeping_导入数据映射文件", "defaultImportReplaceRuleFileName": "ezBookkeeping_导入替换规则文件" }, + "calendar": { + "Gregorian": "公历", + "Buddhist": "佛教日历", + "Gregorian (with Chinese Calendar)": "公历(含农历)" + }, "datetime": { "AM": { "content": "上午" @@ -1498,6 +1510,8 @@ "Default Account": "默认账户", "First Day of Week": "每周第一天", "Fiscal Year Start Date": "财年开始日期", + "Calendar Display Type": "日历显示类型", + "Date Display Type": "日期显示类型", "Long Date Format": "长日期格式", "Short Date Format": "短日期格式", "Long Time Format": "长时间格式", diff --git a/src/locales/zh_Hant.json b/src/locales/zh_Hant.json index 208bf868..02b7dcbb 100644 --- a/src/locales/zh_Hant.json +++ b/src/locales/zh_Hant.json @@ -22,6 +22,8 @@ "currency": "TWD", "firstDayOfWeek": "Sunday", "fiscalYearFormat": "EndYYYY", + "calendarDisplayType": "Gregorian", + "dateDisplayType": "Gregorian", "longDateFormat": "YYYYMMDD", "shortDateFormat": "YYYYMMDD", "longTimeFormat": "AHHMMSS", @@ -73,6 +75,11 @@ "mm_dd_yyyy": "M/D", "dd_mm_yyyy": "D/M" }, + "shortDay": { + "yyyy_mm_dd": "D", + "mm_dd_yyyy": "D", + "dd_mm_yyyy": "D" + }, "longTime": { "hh_mm_ss": "HH:mm:ss", "a_hh_mm_ss": "A hh:mm:ss", @@ -129,6 +136,11 @@ "defaultImportDataMappingFileName": "ezBookkeeping_匯入資料對應檔案", "defaultImportReplaceRuleFileName": "ezBookkeeping_匯入替換規則檔案" }, + "calendar": { + "Gregorian": "公曆", + "Buddhist": "佛曆", + "Gregorian (with Chinese Calendar)": "公曆(含農曆)" + }, "datetime": { "AM": { "content": "上午" @@ -1498,6 +1510,8 @@ "Default Account": "預設帳戶", "First Day of Week": "每週第一天", "Fiscal Year Start Date": "財政年度起始日", + "Calendar Display Type": "日曆顯示類型", + "Date Display Type": "日期顯示類型", "Long Date Format": "長日期格式", "Short Date Format": "短日期格式", "Long Time Format": "長時間格式", diff --git a/src/models/user.ts b/src/models/user.ts index 84f05528..2c2eecc2 100644 --- a/src/models/user.ts +++ b/src/models/user.ts @@ -1,3 +1,4 @@ +import { CalendarDisplayType, DateDisplayType } from '@/core/calendar.ts'; import { LongDateFormat, ShortDateFormat, LongTimeFormat, ShortTimeFormat } from '@/core/datetime.ts'; import { NumeralSystem, DecimalSeparator, DigitGroupingSymbol, DigitGroupingType } from '@/core/numeral.ts'; import { CurrencyDisplayType } from '@/core/currency.ts'; @@ -20,6 +21,8 @@ export class User { public defaultAccountId: string = EMPTY_USER_BASIC_INFO.defaultAccountId; public transactionEditScope: number = EMPTY_USER_BASIC_INFO.transactionEditScope; public fiscalYearStart: number = EMPTY_USER_BASIC_INFO.fiscalYearStart; + public calendarDisplayType: number = EMPTY_USER_BASIC_INFO.calendarDisplayType; + public dateDisplayType: number = EMPTY_USER_BASIC_INFO.dateDisplayType; public longDateFormat: number = EMPTY_USER_BASIC_INFO.longDateFormat; public shortDateFormat: number = EMPTY_USER_BASIC_INFO.shortDateFormat; public longTimeFormat: number = EMPTY_USER_BASIC_INFO.longTimeFormat; @@ -44,12 +47,14 @@ export class User { this.username = user.username; this.email = user.email; this.nickname = user.nickname; + this.defaultAccountId = user.defaultAccountId; + this.transactionEditScope = user.transactionEditScope; this.language = user.language; this.defaultCurrency = user.defaultCurrency; this.firstDayOfWeek = user.firstDayOfWeek; - this.defaultAccountId = user.defaultAccountId; - this.transactionEditScope = user.transactionEditScope; this.fiscalYearStart = user.fiscalYearStart; + this.calendarDisplayType = user.calendarDisplayType; + this.dateDisplayType = user.dateDisplayType; this.longDateFormat = user.longDateFormat; this.shortDateFormat = user.shortDateFormat; this.longTimeFormat = user.longTimeFormat; @@ -90,6 +95,8 @@ export class User { defaultCurrency: this.defaultCurrency, firstDayOfWeek: this.firstDayOfWeek, fiscalYearStart: this.fiscalYearStart, + calendarDisplayType: this.calendarDisplayType, + dateDisplayType: this.dateDisplayType, longDateFormat: this.longDateFormat, shortDateFormat: this.shortDateFormat, longTimeFormat: this.longTimeFormat, @@ -111,6 +118,8 @@ export class User { user.defaultAccountId = userInfo.defaultAccountId; user.transactionEditScope = userInfo.transactionEditScope; user.fiscalYearStart = userInfo.fiscalYearStart; + user.calendarDisplayType = userInfo.calendarDisplayType; + user.dateDisplayType = userInfo.dateDisplayType; user.longDateFormat = userInfo.longDateFormat; user.shortDateFormat = userInfo.shortDateFormat; user.longTimeFormat = userInfo.longTimeFormat; @@ -143,8 +152,10 @@ export interface UserBasicInfo { readonly transactionEditScope: number; readonly language: string; readonly defaultCurrency: string; - readonly fiscalYearStart: number; readonly firstDayOfWeek: number; + readonly fiscalYearStart: number; + readonly calendarDisplayType: number; + readonly dateDisplayType: number; readonly longDateFormat: number; readonly shortDateFormat: number; readonly longTimeFormat: number; @@ -199,6 +210,8 @@ export interface UserProfileUpdateRequest { readonly defaultCurrency?: string; readonly firstDayOfWeek?: number; readonly fiscalYearStart?: number; + readonly calendarDisplayType?: number; + readonly dateDisplayType?: number; readonly longDateFormat?: number; readonly shortDateFormat?: number; readonly longTimeFormat?: number; @@ -235,6 +248,8 @@ export const EMPTY_USER_BASIC_INFO: UserBasicInfo = { defaultCurrency: '', firstDayOfWeek: -1, fiscalYearStart: FiscalYearStart.Default.value, + calendarDisplayType: CalendarDisplayType.Default.type, + dateDisplayType: DateDisplayType.Default.type, longDateFormat: LongDateFormat.Default.type, shortDateFormat: ShortDateFormat.Default.type, longTimeFormat: LongTimeFormat.Default.type, diff --git a/src/stores/user.ts b/src/stores/user.ts index 8f5c066e..197b1014 100644 --- a/src/stores/user.ts +++ b/src/stores/user.ts @@ -3,6 +3,7 @@ import { defineStore } from 'pinia'; import { useSettingsStore } from './setting.ts'; +import { CalendarDisplayType, DateDisplayType } from '@/core/calendar.ts'; import { type WeekDayValue, WeekDay } from '@/core/datetime.ts'; import { FiscalYearStart } from '@/core/fiscalyear.ts'; import type { ApplicationCloudSetting } from '@/core/setting.ts'; @@ -74,6 +75,16 @@ export const useUserStore = defineStore('user', () => { return isNumber(userInfo.fiscalYearStart) && FiscalYearStart.valueOf(userInfo.fiscalYearStart) ? userInfo.fiscalYearStart : EMPTY_USER_BASIC_INFO.fiscalYearStart; }); + const currentUserCalendarDisplayType = computed(() => { + const userInfo = currentUserBasicInfo.value || EMPTY_USER_BASIC_INFO; + return isNumber(userInfo.calendarDisplayType) && CalendarDisplayType.valueOf(userInfo.calendarDisplayType) ? userInfo.calendarDisplayType : EMPTY_USER_BASIC_INFO.calendarDisplayType; + }); + + const currentUserDateDisplayType = computed(() => { + const userInfo = currentUserBasicInfo.value || EMPTY_USER_BASIC_INFO; + return isNumber(userInfo.dateDisplayType) && DateDisplayType.valueOf(userInfo.dateDisplayType) ? userInfo.dateDisplayType : EMPTY_USER_BASIC_INFO.dateDisplayType; + }); + const currentUserLongDateFormat = computed(() => { const userInfo = currentUserBasicInfo.value || EMPTY_USER_BASIC_INFO; return userInfo.longDateFormat; @@ -422,6 +433,8 @@ export const useUserStore = defineStore('user', () => { currentUserDefaultCurrency, currentUserFirstDayOfWeek, currentUserFiscalYearStart, + currentUserCalendarDisplayType, + currentUserDateDisplayType, currentUserLongDateFormat, currentUserShortDateFormat, currentUserLongTimeFormat, diff --git a/src/views/base/accounts/ReconciliationStatementPageBase.ts b/src/views/base/accounts/ReconciliationStatementPageBase.ts index 2755c9e4..6db64671 100644 --- a/src/views/base/accounts/ReconciliationStatementPageBase.ts +++ b/src/views/base/accounts/ReconciliationStatementPageBase.ts @@ -8,7 +8,7 @@ import { useAccountsStore } from '@/stores/account.ts'; import { useTransactionCategoriesStore } from '@/stores/transactionCategory.ts'; import type { TypeAndDisplayName } from '@/core/base.ts'; -import { type WeekDayValue, KnownDateTimeFormat } from '@/core/datetime.ts'; +import type { WeekDayValue } from '@/core/datetime.ts'; import { TransactionType } from '@/core/transaction.ts'; import { KnownFileType } from '@/core/file.ts'; import type { Account } from '@/models/account.ts'; @@ -23,8 +23,7 @@ import { replaceAll } from '@/lib/common.ts'; import { getUtcOffsetByUtcOffsetMinutes, getTimezoneOffsetMinutes, - parseDateTimeFromUnixTime, - formatUnixTime + parseDateTimeFromUnixTime } from '@/lib/datetime.ts'; export function useReconciliationStatementPageBase() { @@ -32,6 +31,7 @@ export function useReconciliationStatementPageBase() { tt, getAllAccountBalanceTrendChartTypes, getAllStatisticsDateAggregationTypesWithShortName, + formatUnixTimeToDefaultDateTimeWithoutLocaleOptions, formatUnixTimeToLongDateTime, formatUnixTimeToLongDate, formatUnixTimeToShortTime, @@ -241,7 +241,7 @@ export function useReconciliationStatementPageBase() { } return [ - formatUnixTime(transactionTime, KnownDateTimeFormat.DefaultDateTime.format), + formatUnixTimeToDefaultDateTimeWithoutLocaleOptions(transactionTime), type, categoryName, displayAmount, diff --git a/src/views/base/users/UserProfilePageBase.ts b/src/views/base/users/UserProfilePageBase.ts index 3a5ca9d8..e4a1382b 100644 --- a/src/views/base/users/UserProfilePageBase.ts +++ b/src/views/base/users/UserProfilePageBase.ts @@ -7,6 +7,7 @@ import { useAccountsStore } from '@/stores/account.ts'; import { useOverviewStore } from '@/stores/overview.ts'; import type { TypeAndDisplayName } from '@/core/base.ts'; +import { DateDisplayType } from '@/core/calendar.ts'; import { WeekDay } from '@/core/datetime.ts'; import { type LocalizedDigitGroupingType, NumeralSystem, DecimalSeparator, DigitGroupingSymbol } from '@/core/numeral.ts'; @@ -22,6 +23,8 @@ export function useUserProfilePageBase() { getDefaultCurrency, getDefaultFirstDayOfWeek, getAllWeekDays, + getAllCalendarDisplayTypes, + getAllDateDisplayTypes, getAllLongDateFormats, getAllShortDateFormats, getAllLongTimeFormats, @@ -58,8 +61,10 @@ export function useUserProfilePageBase() { const allVisibleAccounts = computed(() => accountsStore.allVisiblePlainAccounts); const allVisibleCategorizedAccounts = computed(() => getCategorizedAccounts(allVisibleAccounts.value)); const allWeekDays = computed(() => getAllWeekDays()); - const allLongDateFormats = computed(() => getAllLongDateFormats()); - const allShortDateFormats = computed(() => getAllShortDateFormats()); + const allCalendarDisplayTypes = computed(() => getAllCalendarDisplayTypes()); + const allDateDisplayTypes = computed(() => getAllDateDisplayTypes()); + const allLongDateFormats = computed(() => getAllLongDateFormats(DateDisplayType.valueOf(newProfile.value.dateDisplayType)?.calendarType)); + const allShortDateFormats = computed(() => getAllShortDateFormats(DateDisplayType.valueOf(newProfile.value.dateDisplayType)?.calendarType)); const allLongTimeFormats = computed(() => getAllLongTimeFormats()); const allShortTimeFormats = computed(() => getAllShortTimeFormats()); const allFiscalYearFormats = computed(() => getAllFiscalYearFormats()); @@ -105,6 +110,8 @@ export function useUserProfilePageBase() { newProfile.value.defaultCurrency === oldProfile.value.defaultCurrency && newProfile.value.fiscalYearStart === oldProfile.value.fiscalYearStart && newProfile.value.firstDayOfWeek === oldProfile.value.firstDayOfWeek && + newProfile.value.calendarDisplayType === oldProfile.value.calendarDisplayType && + newProfile.value.dateDisplayType === oldProfile.value.dateDisplayType && newProfile.value.longDateFormat === oldProfile.value.longDateFormat && newProfile.value.shortDateFormat === oldProfile.value.shortDateFormat && newProfile.value.longTimeFormat === oldProfile.value.longTimeFormat && @@ -197,6 +204,8 @@ export function useUserProfilePageBase() { allVisibleAccounts, allVisibleCategorizedAccounts, allWeekDays, + allCalendarDisplayTypes, + allDateDisplayTypes, allLongDateFormats, allShortDateFormats, allLongTimeFormats, diff --git a/src/views/desktop/overview/cards/MonthlyIncomeAndExpenseCard.vue b/src/views/desktop/overview/cards/MonthlyIncomeAndExpenseCard.vue index be8dfbd2..4697e2d0 100644 --- a/src/views/desktop/overview/cards/MonthlyIncomeAndExpenseCard.vue +++ b/src/views/desktop/overview/cards/MonthlyIncomeAndExpenseCard.vue @@ -41,7 +41,6 @@ import { DISPLAY_HIDDEN_AMOUNT, INCOMPLETE_AMOUNT_SUFFIX } from '@/consts/numera import { type TransactionMonthlyIncomeAndExpenseData } from '@/models/transaction.ts'; -import { parseDateTimeFromUnixTime } from '@/lib/datetime.ts'; import { getExpenseAndIncomeAmountColor } from '@/lib/ui/common.ts'; export interface MonthlyIncomeAndExpenseCardClickEvent { @@ -61,7 +60,7 @@ const emit = defineEmits<{ (e: 'click', event: MonthlyIncomeAndExpenseCardClickEvent): void; }>(); -const { tt, getCurrentLanguageTextDirection, formatAmountToLocalizedNumeralsWithCurrency } = useI18n(); +const { tt, getCurrentLanguageTextDirection, formatUnixTimeToShortMonth, formatAmountToLocalizedNumeralsWithCurrency } = useI18n(); const settingsStore = useSettingsStore(); const userStore = useUserStore(); @@ -97,7 +96,7 @@ const chartOptions = computed(() => { if (props.data) { for (let i = 0; i < props.data.length; i++) { const item = props.data[i]; - const monthShortName = parseDateTimeFromUnixTime(item.monthStartTime).getGregorianCalendarMonthDisplayShortName(); + const monthShortName = formatUnixTimeToShortMonth(item.monthStartTime); monthNames.push(monthShortName); incomeAmounts.push(item.incomeAmount); diff --git a/src/views/desktop/user/settings/tabs/UserBasicSettingTab.vue b/src/views/desktop/user/settings/tabs/UserBasicSettingTab.vue index 6204c148..e4d1d789 100644 --- a/src/views/desktop/user/settings/tabs/UserBasicSettingTab.vue +++ b/src/views/desktop/user/settings/tabs/UserBasicSettingTab.vue @@ -159,6 +159,32 @@ + + + + + + + + (settingsStore.appSettings.fontSize); const textDirection = computed(() => getCurrentLanguageTextDirection()); const fontSizePreviewClassName = computed(() => getFontSizePreviewClassName(fontSize.value)); const currentLongYearMonth = computed(() => formatUnixTimeToLongYearMonth(currentUnixTime.value)); -const currentDayOfMonth = computed(() => parseDateTimeFromUnixTime(currentUnixTime.value).getLocalizedCalendarDay()); +const currentDayOfMonth = computed(() => formatUnixTimeToDayOfMonth(currentUnixTime.value)); const currentDayOfWeek = computed(() => getWeekdayShortName(parseDateTimeFromUnixTime(currentUnixTime.value).getWeekDay())); const currentShortTime = computed(() => formatUnixTimeToShortTime(currentUnixTime.value)); diff --git a/src/views/mobile/transactions/ListPage.vue b/src/views/mobile/transactions/ListPage.vue index b00ed7d0..63d3d948 100644 --- a/src/views/mobile/transactions/ListPage.vue +++ b/src/views/mobile/transactions/ListPage.vue @@ -222,7 +222,7 @@