mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-19 09:14:27 +08:00
calendar display type supports Gregorian with Chinese
This commit is contained in:
@@ -7,10 +7,11 @@ type CalendarDisplayType byte
|
|||||||
|
|
||||||
// Calendar Display Type
|
// Calendar Display Type
|
||||||
const (
|
const (
|
||||||
CALENDAR_DISPLAY_TYPE_DEFAULT CalendarDisplayType = 0
|
CALENDAR_DISPLAY_TYPE_DEFAULT CalendarDisplayType = 0
|
||||||
CALENDAR_DISPLAY_TYPE_GREGORAIN CalendarDisplayType = 1
|
CALENDAR_DISPLAY_TYPE_GREGORAIN CalendarDisplayType = 1
|
||||||
CALENDAR_DISPLAY_TYPE_BUDDHIST CalendarDisplayType = 2
|
CALENDAR_DISPLAY_TYPE_BUDDHIST CalendarDisplayType = 2
|
||||||
CALENDAR_DISPLAY_TYPE_INVALID CalendarDisplayType = 255
|
CALENDAR_DISPLAY_TYPE_GREGORAIN_WITH_CHINESE CalendarDisplayType = 3
|
||||||
|
CALENDAR_DISPLAY_TYPE_INVALID CalendarDisplayType = 255
|
||||||
)
|
)
|
||||||
|
|
||||||
// String returns a textual representation of the calendar display type enum
|
// String returns a textual representation of the calendar display type enum
|
||||||
@@ -22,6 +23,8 @@ func (f CalendarDisplayType) String() string {
|
|||||||
return "Gregorian"
|
return "Gregorian"
|
||||||
case CALENDAR_DISPLAY_TYPE_BUDDHIST:
|
case CALENDAR_DISPLAY_TYPE_BUDDHIST:
|
||||||
return "Buddhist"
|
return "Buddhist"
|
||||||
|
case CALENDAR_DISPLAY_TYPE_GREGORAIN_WITH_CHINESE:
|
||||||
|
return "Gregorian with Chinese"
|
||||||
case CALENDAR_DISPLAY_TYPE_INVALID:
|
case CALENDAR_DISPLAY_TYPE_INVALID:
|
||||||
return "Invalid"
|
return "Invalid"
|
||||||
default:
|
default:
|
||||||
|
|||||||
+1
-1
@@ -199,7 +199,7 @@ type UserProfileUpdateRequest struct {
|
|||||||
DefaultCurrency string `json:"defaultCurrency" binding:"omitempty,len=3,validCurrency"`
|
DefaultCurrency string `json:"defaultCurrency" binding:"omitempty,len=3,validCurrency"`
|
||||||
FirstDayOfWeek *core.WeekDay `json:"firstDayOfWeek" binding:"omitempty,min=0,max=6"`
|
FirstDayOfWeek *core.WeekDay `json:"firstDayOfWeek" binding:"omitempty,min=0,max=6"`
|
||||||
FiscalYearStart *core.FiscalYearStart `json:"fiscalYearStart" binding:"omitempty,validFiscalYearStart"`
|
FiscalYearStart *core.FiscalYearStart `json:"fiscalYearStart" binding:"omitempty,validFiscalYearStart"`
|
||||||
CalendarDisplayType *core.CalendarDisplayType `json:"calendarDisplayType" binding:"omitempty,min=0,max=2"`
|
CalendarDisplayType *core.CalendarDisplayType `json:"calendarDisplayType" binding:"omitempty,min=0,max=3"`
|
||||||
DateDisplayType *core.DateDisplayType `json:"dateDisplayType" binding:"omitempty,min=0,max=2"`
|
DateDisplayType *core.DateDisplayType `json:"dateDisplayType" binding:"omitempty,min=0,max=2"`
|
||||||
LongDateFormat *core.LongDateFormat `json:"longDateFormat" binding:"omitempty,min=0,max=3"`
|
LongDateFormat *core.LongDateFormat `json:"longDateFormat" binding:"omitempty,min=0,max=3"`
|
||||||
ShortDateFormat *core.ShortDateFormat `json:"shortDateFormat" binding:"omitempty,min=0,max=3"`
|
ShortDateFormat *core.ShortDateFormat `json:"shortDateFormat" binding:"omitempty,min=0,max=3"`
|
||||||
|
|||||||
@@ -293,7 +293,7 @@ func (s *UserService) UpdateUser(c core.Context, user *models.User, modifyUserLa
|
|||||||
updateCols = append(updateCols, "fiscal_year_start")
|
updateCols = append(updateCols, "fiscal_year_start")
|
||||||
}
|
}
|
||||||
|
|
||||||
if core.CALENDAR_DISPLAY_TYPE_DEFAULT <= user.CalendarDisplayType && user.CalendarDisplayType <= core.CALENDAR_DISPLAY_TYPE_BUDDHIST {
|
if core.CALENDAR_DISPLAY_TYPE_DEFAULT <= user.CalendarDisplayType && user.CalendarDisplayType <= core.CALENDAR_DISPLAY_TYPE_GREGORAIN_WITH_CHINESE {
|
||||||
updateCols = append(updateCols, "calendar_display_type")
|
updateCols = append(updateCols, "calendar_display_type")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
inline auto-apply
|
inline auto-apply
|
||||||
enable-seconds
|
enable-seconds
|
||||||
six-weeks="center"
|
six-weeks="center"
|
||||||
:class="datetimePickerClass"
|
:class="`datetime-picker ${showAlternateDates && alternateCalendarType ? 'datetime-picker-with-alternate-date' : ''} ${datetimePickerClass}`"
|
||||||
:config="noSwipeAndScroll ? { noSwipe: true } : undefined"
|
:config="noSwipeAndScroll ? { noSwipe: true } : undefined"
|
||||||
:dark="isDarkMode"
|
:dark="isDarkMode"
|
||||||
:vertical="vertical"
|
:vertical="vertical"
|
||||||
@@ -35,7 +35,10 @@
|
|||||||
{{ getDisplayMonth(value) }}
|
{{ getDisplayMonth(value) }}
|
||||||
</template>
|
</template>
|
||||||
<template #day="{ date }">
|
<template #day="{ date }">
|
||||||
{{ getDisplayDay(date) }}
|
<div class="datetime-picker-display-dates">
|
||||||
|
<span>{{ getDisplayDay(date) }}</span>
|
||||||
|
<span class="datetime-picker-alternate-date" v-if="showAlternateDates && alternateCalendarType && getAlternateDate(date)">{{ getAlternateDate(date) }}</span>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #am-pm-button="{ toggle, value }">
|
<template #am-pm-button="{ toggle, value }">
|
||||||
<button class="dp__pm_am_button" tabindex="0" @click="toggle">{{ tt(`datetime.${value}.content`) }}</button>
|
<button class="dp__pm_am_button" tabindex="0" @click="toggle">{{ tt(`datetime.${value}.content`) }}</button>
|
||||||
@@ -51,7 +54,8 @@ import { useI18n } from '@/locales/helpers.ts';
|
|||||||
|
|
||||||
import { useUserStore } from '@/stores/user.ts';
|
import { useUserStore } from '@/stores/user.ts';
|
||||||
|
|
||||||
import { type PresetDateRange, type WeekDayValue } from '@/core/datetime.ts';
|
import type { CalendarType } from '@/core/calendar.ts';
|
||||||
|
import type { PresetDateRange, WeekDayValue } from '@/core/datetime.ts';
|
||||||
import { isArray, arrangeArrayWithNewStartIndex } from '@/lib/common.ts';
|
import { isArray, arrangeArrayWithNewStartIndex } from '@/lib/common.ts';
|
||||||
import { getAllowedYearRange, getYearMonthDayDateTime } from '@/lib/datetime.ts';
|
import { getAllowedYearRange, getYearMonthDayDateTime } from '@/lib/datetime.ts';
|
||||||
|
|
||||||
@@ -70,6 +74,7 @@ const props = defineProps<{
|
|||||||
minDate?: Date;
|
minDate?: Date;
|
||||||
maxDate?: Date;
|
maxDate?: Date;
|
||||||
disabledDates?: (date: Date) => boolean;
|
disabledDates?: (date: Date) => boolean;
|
||||||
|
showAlternateDates?: boolean;
|
||||||
presetRanges?: PresetDateRange[];
|
presetRanges?: PresetDateRange[];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
@@ -80,11 +85,13 @@ const emit = defineEmits<{
|
|||||||
const {
|
const {
|
||||||
tt,
|
tt,
|
||||||
getAllMinWeekdayNames,
|
getAllMinWeekdayNames,
|
||||||
|
getCurrentCalendarDisplayType,
|
||||||
isLongDateMonthAfterYear,
|
isLongDateMonthAfterYear,
|
||||||
isLongTime24HourFormat,
|
isLongTime24HourFormat,
|
||||||
getCalendarShortYearFromUnixTime,
|
getCalendarShortYearFromUnixTime,
|
||||||
getCalendarShortMonthFromUnixTime,
|
getCalendarShortMonthFromUnixTime,
|
||||||
getCalendarDayOfMonthFromUnixTime
|
getCalendarDayOfMonthFromUnixTime,
|
||||||
|
getCalendarAlternateDate
|
||||||
} = useI18n();
|
} = useI18n();
|
||||||
|
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
@@ -97,6 +104,7 @@ const dayNames = computed<string[]>(() => arrangeArrayWithNewStartIndex(getAllMi
|
|||||||
const firstDayOfWeek = computed<WeekDayValue>(() => userStore.currentUserFirstDayOfWeek);
|
const firstDayOfWeek = computed<WeekDayValue>(() => userStore.currentUserFirstDayOfWeek);
|
||||||
const isYearFirst = computed<boolean>(() => isLongDateMonthAfterYear());
|
const isYearFirst = computed<boolean>(() => isLongDateMonthAfterYear());
|
||||||
const is24Hour = computed<boolean>(() => isLongTime24HourFormat());
|
const is24Hour = computed<boolean>(() => isLongTime24HourFormat());
|
||||||
|
const alternateCalendarType = computed<CalendarType | undefined>(() => getCurrentCalendarDisplayType().secondaryCalendarType);
|
||||||
|
|
||||||
const dateTime = computed<SupportedModelValue>({
|
const dateTime = computed<SupportedModelValue>({
|
||||||
get: () => props.modelValue,
|
get: () => props.modelValue,
|
||||||
@@ -105,6 +113,18 @@ const dateTime = computed<SupportedModelValue>({
|
|||||||
|
|
||||||
const isDateRange = computed<boolean>(() => isArray(props.modelValue));
|
const isDateRange = computed<boolean>(() => isArray(props.modelValue));
|
||||||
|
|
||||||
|
function getAlternateDate(date: Date): string | undefined {
|
||||||
|
if (!props.showAlternateDates) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return getCalendarAlternateDate({
|
||||||
|
year: date.getFullYear(),
|
||||||
|
month: date.getMonth() + 1,
|
||||||
|
day: date.getDate()
|
||||||
|
})?.displayDate;
|
||||||
|
};
|
||||||
|
|
||||||
function switchView(viewType: MenuView): void {
|
function switchView(viewType: MenuView): void {
|
||||||
datetimepicker.value?.switchView(viewType);
|
datetimepicker.value?.switchView(viewType);
|
||||||
}
|
}
|
||||||
@@ -131,3 +151,35 @@ defineExpose({
|
|||||||
switchView
|
switchView
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.datetime-picker-display-dates {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetime-picker-alternate-date {
|
||||||
|
margin-top: -2px;
|
||||||
|
opacity: 0.5;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dp__cell_disabled .datetime-picker-alternate-date,
|
||||||
|
.dp__cell_offset .datetime-picker-alternate-date {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dp__main.datetime-picker .dp__calendar .dp__calendar_row > .dp__calendar_item .datetime-picker-display-dates > span.datetime-picker-alternate-date {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dp__main.datetime-picker.datetime-picker-with-alternate-date .dp__calendar .dp__calendar_row {
|
||||||
|
--dp-cell-size: 45px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<vue-date-picker inline auto-apply
|
<vue-date-picker inline auto-apply
|
||||||
model-type="yyyy-MM-dd"
|
model-type="yyyy-MM-dd"
|
||||||
:class="`transaction-calendar ${calendarClass}`"
|
:class="`transaction-calendar ${alternateDates ? 'transaction-calendar-with-alternate-date' : ''} ${calendarClass}`"
|
||||||
:config="{ noSwipe: true }"
|
:config="{ noSwipe: true }"
|
||||||
:readonly="readonly"
|
:readonly="readonly"
|
||||||
:dark="isDarkMode"
|
:dark="isDarkMode"
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
<template #day="{ day, date }">
|
<template #day="{ day, date }">
|
||||||
<div class="transaction-calendar-daily-amounts">
|
<div class="transaction-calendar-daily-amounts">
|
||||||
<span :class="dayHasTransactionClass && dailyTotalAmounts && dailyTotalAmounts[day] ? dayHasTransactionClass : undefined">{{ getDisplayDay(date) }}</span>
|
<span :class="dayHasTransactionClass && dailyTotalAmounts && dailyTotalAmounts[day] ? dayHasTransactionClass : undefined">{{ getDisplayDay(date) }}</span>
|
||||||
|
<span class="transaction-calendar-alternate-date" v-if="alternateDates && alternateDates[`${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`]">{{ alternateDates[`${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`] }}</span>
|
||||||
<span class="transaction-calendar-daily-amount text-income" v-if="dailyTotalAmounts && dailyTotalAmounts[day] && dailyTotalAmounts[day].income">{{ getDisplayMonthTotalAmount(dailyTotalAmounts[day].income, defaultCurrency, '', dailyTotalAmounts[day].incompleteIncome) }}</span>
|
<span class="transaction-calendar-daily-amount text-income" v-if="dailyTotalAmounts && dailyTotalAmounts[day] && dailyTotalAmounts[day].income">{{ getDisplayMonthTotalAmount(dailyTotalAmounts[day].income, defaultCurrency, '', dailyTotalAmounts[day].incompleteIncome) }}</span>
|
||||||
<span class="transaction-calendar-daily-amount text-expense" v-if="dailyTotalAmounts && dailyTotalAmounts[day] && dailyTotalAmounts[day].expense">{{ getDisplayMonthTotalAmount(dailyTotalAmounts[day].expense, defaultCurrency, '', dailyTotalAmounts[day].incompleteExpense) }}</span>
|
<span class="transaction-calendar-daily-amount text-expense" v-if="dailyTotalAmounts && dailyTotalAmounts[day] && dailyTotalAmounts[day].expense">{{ getDisplayMonthTotalAmount(dailyTotalAmounts[day].expense, defaultCurrency, '', dailyTotalAmounts[day].incompleteExpense) }}</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -35,7 +36,7 @@ import { useI18n } from '@/locales/helpers.ts';
|
|||||||
import { useUserStore } from '@/stores/user.ts';
|
import { useUserStore } from '@/stores/user.ts';
|
||||||
import type { TransactionTotalAmount } from '@/stores/transaction.ts';
|
import type { TransactionTotalAmount } from '@/stores/transaction.ts';
|
||||||
|
|
||||||
import { type TextualYearMonthDay, type WeekDayValue } from '@/core/datetime.ts';
|
import type { CalendarAlternateDate, TextualYearMonthDay, WeekDayValue } from '@/core/datetime.ts';
|
||||||
import { INCOMPLETE_AMOUNT_SUFFIX } from '@/consts/numeral.ts';
|
import { INCOMPLETE_AMOUNT_SUFFIX } from '@/consts/numeral.ts';
|
||||||
|
|
||||||
import { arrangeArrayWithNewStartIndex } from '@/lib/common.ts';
|
import { arrangeArrayWithNewStartIndex } from '@/lib/common.ts';
|
||||||
@@ -69,6 +70,7 @@ const {
|
|||||||
getAllLongWeekdayNames,
|
getAllLongWeekdayNames,
|
||||||
getAllShortWeekdayNames,
|
getAllShortWeekdayNames,
|
||||||
getCalendarDayOfMonthFromUnixTime,
|
getCalendarDayOfMonthFromUnixTime,
|
||||||
|
getCalendarAlternateDates,
|
||||||
formatAmountToLocalizedNumeralsWithCurrency
|
formatAmountToLocalizedNumeralsWithCurrency
|
||||||
} = useI18n();
|
} = useI18n();
|
||||||
|
|
||||||
@@ -82,6 +84,28 @@ const dateTime = computed<TextualYearMonthDay | ''>({
|
|||||||
set: (value: TextualYearMonthDay | '') => emit('update:modelValue', value)
|
set: (value: TextualYearMonthDay | '') => emit('update:modelValue', value)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const alternateDates = computed<Record<TextualYearMonthDay, string> | undefined>(() => {
|
||||||
|
const yearMonthDay = props.modelValue ? props.modelValue.split('-') : null;
|
||||||
|
|
||||||
|
if (!yearMonthDay || yearMonthDay.length !== 3) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const allDates: CalendarAlternateDate[] | undefined = getCalendarAlternateDates({ year: parseInt(yearMonthDay[0]), month1base: parseInt(yearMonthDay[1]) })
|
||||||
|
|
||||||
|
if (!allDates) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ret: Record<TextualYearMonthDay, string> = {};
|
||||||
|
|
||||||
|
for (const alternateDate of allDates) {
|
||||||
|
ret[`${alternateDate.year}-${alternateDate.month}-${alternateDate.day}`] = alternateDate.displayDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
});
|
||||||
|
|
||||||
function noTransactionInMonthDay(date: Date): boolean {
|
function noTransactionInMonthDay(date: Date): boolean {
|
||||||
const dateTime = parseDateTimeFromUnixTime(getActualUnixTimeForStore(getUnixTimeFromLocalDatetime(date), getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes()));
|
const dateTime = parseDateTimeFromUnixTime(getActualUnixTimeForStore(getUnixTimeFromLocalDatetime(date), getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes()));
|
||||||
return !props.dailyTotalAmounts || !props.dailyTotalAmounts[dateTime.getGregorianCalendarDay()];
|
return !props.dailyTotalAmounts || !props.dailyTotalAmounts[dateTime.getGregorianCalendarDay()];
|
||||||
@@ -105,7 +129,17 @@ function getDisplayDay(date: Date): string {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.transaction-calendar.dp__main .dp__calendar .dp__calendar_row > .dp__calendar_item .transaction-calendar-daily-amounts > span.transaction-calendar-daily-amount {
|
.transaction-calendar-alternate-date {
|
||||||
|
margin-top: -3px;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dp__cell_disabled .transaction-calendar-alternate-date {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dp__main.transaction-calendar .dp__calendar .dp__calendar_row > .dp__calendar_item .transaction-calendar-daily-amounts > span.transaction-calendar-alternate-date,
|
||||||
|
.dp__main.transaction-calendar .dp__calendar .dp__calendar_row > .dp__calendar_item .transaction-calendar-daily-amounts > span.transaction-calendar-daily-amount {
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
:enable-time-picker="true"
|
:enable-time-picker="true"
|
||||||
:vertical="true"
|
:vertical="true"
|
||||||
:preset-dates="presetRanges"
|
:preset-dates="presetRanges"
|
||||||
|
:show-alternate-dates="true"
|
||||||
v-model="dateRange">
|
v-model="dateRange">
|
||||||
</date-time-picker>
|
</date-time-picker>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
<date-time-picker :is-dark-mode="isDarkMode"
|
<date-time-picker :is-dark-mode="isDarkMode"
|
||||||
:enable-time-picker="false"
|
:enable-time-picker="false"
|
||||||
:clearable="true"
|
:clearable="true"
|
||||||
|
:show-alternate-dates="true"
|
||||||
v-model="dateTime">
|
v-model="dateTime">
|
||||||
</date-time-picker>
|
</date-time-picker>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
<date-time-picker :is-dark-mode="isDarkMode"
|
<date-time-picker :is-dark-mode="isDarkMode"
|
||||||
:enable-time-picker="false"
|
:enable-time-picker="false"
|
||||||
:vertical="true"
|
:vertical="true"
|
||||||
|
:show-alternate-dates="true"
|
||||||
v-model="dateTime">
|
v-model="dateTime">
|
||||||
</date-time-picker>
|
</date-time-picker>
|
||||||
<div class="date-time-select-time-picker-container">
|
<div class="date-time-select-time-picker-container">
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
:is-dark-mode="isDarkMode"
|
:is-dark-mode="isDarkMode"
|
||||||
:enable-time-picker="true"
|
:enable-time-picker="true"
|
||||||
:preset-dates="presetRanges"
|
:preset-dates="presetRanges"
|
||||||
|
:show-alternate-dates="true"
|
||||||
v-model="dateRange">
|
v-model="dateRange">
|
||||||
</date-time-picker>
|
</date-time-picker>
|
||||||
<f7-button large fill
|
<f7-button large fill
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
:is-dark-mode="isDarkMode"
|
:is-dark-mode="isDarkMode"
|
||||||
:enable-time-picker="false"
|
:enable-time-picker="false"
|
||||||
:clearable="true"
|
:clearable="true"
|
||||||
|
:show-alternate-dates="true"
|
||||||
v-model="dateTime">
|
v-model="dateTime">
|
||||||
</date-time-picker>
|
</date-time-picker>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
datetime-picker-class="justify-content-center"
|
datetime-picker-class="justify-content-center"
|
||||||
:is-dark-mode="isDarkMode"
|
:is-dark-mode="isDarkMode"
|
||||||
:enable-time-picker="false"
|
:enable-time-picker="false"
|
||||||
|
:show-alternate-dates="true"
|
||||||
v-model="dateTime"
|
v-model="dateTime"
|
||||||
v-show="mode === 'date'">
|
v-show="mode === 'date'">
|
||||||
</date-time-picker>
|
</date-time-picker>
|
||||||
|
|||||||
+11
-1
@@ -2,7 +2,16 @@ import type { TypeAndName } from '@/core/base.ts';
|
|||||||
|
|
||||||
export enum CalendarType {
|
export enum CalendarType {
|
||||||
Gregorian = 0,
|
Gregorian = 0,
|
||||||
Buddhist = 1
|
Buddhist = 1,
|
||||||
|
Chinese = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ChineseCalendarLocaleData {
|
||||||
|
readonly numerals: string[];
|
||||||
|
readonly monthNames: string[];
|
||||||
|
readonly dayNames: string[];
|
||||||
|
readonly leapMonthPrefix: string;
|
||||||
|
readonly solarTermNames: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CalendarDisplayType implements TypeAndName {
|
export class CalendarDisplayType implements TypeAndName {
|
||||||
@@ -13,6 +22,7 @@ export class CalendarDisplayType implements TypeAndName {
|
|||||||
public static readonly LanguageDefaultType: number = 0;
|
public static readonly LanguageDefaultType: number = 0;
|
||||||
public static readonly Gregorian = new CalendarDisplayType(1, 'Gregorian', 'Gregorian', CalendarType.Gregorian);
|
public static readonly Gregorian = new CalendarDisplayType(1, 'Gregorian', 'Gregorian', CalendarType.Gregorian);
|
||||||
public static readonly Buddhist = new CalendarDisplayType(2, 'Buddhist', 'Buddhist', CalendarType.Buddhist);
|
public static readonly Buddhist = new CalendarDisplayType(2, 'Buddhist', 'Buddhist', CalendarType.Buddhist);
|
||||||
|
public static readonly GregorianWithChinese = new CalendarDisplayType(3, 'GregorianWithChinese', 'Gregorian with Chinese', CalendarType.Gregorian, CalendarType.Chinese);
|
||||||
|
|
||||||
public static readonly Default = CalendarDisplayType.Gregorian;
|
public static readonly Default = CalendarDisplayType.Gregorian;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { TypeAndName, TypeAndDisplayName } from '@/core/base.ts';
|
import type { TypeAndName, TypeAndDisplayName } from '@/core/base.ts';
|
||||||
import type { CalendarType } from '@/core/calendar.ts';
|
import type { CalendarType, ChineseCalendarLocaleData } from '@/core/calendar.ts';
|
||||||
import type { NumeralSystem } from '@/core/numeral.ts';
|
import type { NumeralSystem } from '@/core/numeral.ts';
|
||||||
|
|
||||||
export interface DateTime {
|
export interface DateTime {
|
||||||
@@ -12,7 +12,6 @@ export interface DateTime {
|
|||||||
getGregorianCalendarMonthDisplayName(options: DateTimeFormatOptions): string;
|
getGregorianCalendarMonthDisplayName(options: DateTimeFormatOptions): string;
|
||||||
getGregorianCalendarMonthDisplayShortName(options: DateTimeFormatOptions): string;
|
getGregorianCalendarMonthDisplayShortName(options: DateTimeFormatOptions): string;
|
||||||
getLocalizedCalendarMonth(options: DateTimeFormatOptions): string;
|
getLocalizedCalendarMonth(options: DateTimeFormatOptions): string;
|
||||||
getLocalizedCalendarMonthIndex(options: DateTimeFormatOptions): number;
|
|
||||||
getLocalizedCalendarMonthDisplayName(options: DateTimeFormatOptions): string;
|
getLocalizedCalendarMonthDisplayName(options: DateTimeFormatOptions): string;
|
||||||
getLocalizedCalendarMonthDisplayShortName(options: DateTimeFormatOptions): string;
|
getLocalizedCalendarMonthDisplayShortName(options: DateTimeFormatOptions): string;
|
||||||
getGregorianCalendarDay(): number;
|
getGregorianCalendarDay(): number;
|
||||||
@@ -37,6 +36,7 @@ export interface DateTimeFormatOptions {
|
|||||||
numeralSystem: NumeralSystem;
|
numeralSystem: NumeralSystem;
|
||||||
calendarType: CalendarType;
|
calendarType: CalendarType;
|
||||||
localeData: DateTimeLocaleData;
|
localeData: DateTimeLocaleData;
|
||||||
|
chineseCalendarLocaleData: ChineseCalendarLocaleData;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DateTimeLocaleData {
|
export interface DateTimeLocaleData {
|
||||||
@@ -82,6 +82,10 @@ export interface MonthDay {
|
|||||||
readonly day: number;
|
readonly day: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface CalendarAlternateDate extends YearMonthDay {
|
||||||
|
readonly displayDate: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface TimeRange {
|
export interface TimeRange {
|
||||||
readonly minTime: number;
|
readonly minTime: number;
|
||||||
readonly maxTime: number;
|
readonly maxTime: number;
|
||||||
|
|||||||
@@ -0,0 +1,152 @@
|
|||||||
|
import fs from "fs";
|
||||||
|
import path from 'path';
|
||||||
|
import { describe, expect, test } from '@jest/globals';
|
||||||
|
|
||||||
|
import { DEFAULT_CONTENT } from '@/locales/calendar/chinese/index.ts';
|
||||||
|
import type { ChineseCalendarLocaleData } from '@/core/calendar.ts';
|
||||||
|
import {
|
||||||
|
type ChineseYearMonthDayInfo,
|
||||||
|
getChineseYearMonthAllDayInfos,
|
||||||
|
getChineseYearMonthDayInfo
|
||||||
|
} from '@/lib/calendar/chinese_calendar.ts';
|
||||||
|
|
||||||
|
const defaultLocaleData: ChineseCalendarLocaleData = DEFAULT_CONTENT;
|
||||||
|
const localeData: ChineseCalendarLocaleData = {
|
||||||
|
numerals: defaultLocaleData.numerals,
|
||||||
|
monthNames: defaultLocaleData.monthNames,
|
||||||
|
dayNames: defaultLocaleData.dayNames,
|
||||||
|
leapMonthPrefix: defaultLocaleData.leapMonthPrefix,
|
||||||
|
solarTermNames: [
|
||||||
|
'Moderate Cold',
|
||||||
|
'Severe Cold',
|
||||||
|
'Spring Commences',
|
||||||
|
'Spring Showers',
|
||||||
|
'Insects Waken',
|
||||||
|
'Vernal Equinox',
|
||||||
|
'Bright & Clear',
|
||||||
|
'Corn Rain',
|
||||||
|
'Summer Commences',
|
||||||
|
'Corn Forms',
|
||||||
|
'Corn on Ear',
|
||||||
|
'Summer Solstice',
|
||||||
|
'Moderate Heat',
|
||||||
|
'Great Heat',
|
||||||
|
'Autumn Commences',
|
||||||
|
'End of Heat',
|
||||||
|
'White Dew',
|
||||||
|
'Autumnal Equinox',
|
||||||
|
'Cold Dew',
|
||||||
|
'Frost',
|
||||||
|
'Winter Commences',
|
||||||
|
'Light Snow',
|
||||||
|
'Heavy Snow',
|
||||||
|
'Winter Solstice'
|
||||||
|
]
|
||||||
|
};
|
||||||
|
const ordinalSuffix = ['st', 'nd', 'rd'];
|
||||||
|
|
||||||
|
describe('getChineseYearMonthAllDayInfos', () => {
|
||||||
|
const lines: string[] = fs.readFileSync(path.join(__dirname, 'chinese_calendar_all_data.txt'), 'utf8').split('\n');
|
||||||
|
const allMonthChineseDays: Record<string, string[]> = {};
|
||||||
|
const allMonthSolarTermNames: Record<string, string[]> = {};
|
||||||
|
let currentMonthChineseDays: string[] = [];
|
||||||
|
let currentMonthSolarTermNames: string[] = [];
|
||||||
|
let currentYear: number = 0;
|
||||||
|
let currentMonth: number = 0;
|
||||||
|
|
||||||
|
for (const line of lines) {
|
||||||
|
if (!line.trim() || line.startsWith('#')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const items = line.split('\t');
|
||||||
|
const gregorianDate = items[0];
|
||||||
|
const gregorianDateItems = gregorianDate.split('/');
|
||||||
|
const gregorianYear = parseInt(gregorianDateItems[0], 10);
|
||||||
|
const gregorianMonth = parseInt(gregorianDateItems[1], 10);
|
||||||
|
const chineseDay = items[1];
|
||||||
|
const solarTermName = items.length > 3 ? items[3] : '';
|
||||||
|
|
||||||
|
if (currentYear > 0 && currentMonth > 0 && (gregorianYear !== currentYear || gregorianMonth !== currentMonth)) {
|
||||||
|
allMonthChineseDays[`${currentYear}-${currentMonth}`] = currentMonthChineseDays;
|
||||||
|
allMonthSolarTermNames[`${currentYear}-${currentMonth}`] = currentMonthSolarTermNames;
|
||||||
|
|
||||||
|
currentMonthChineseDays = [];
|
||||||
|
currentMonthSolarTermNames = [];
|
||||||
|
|
||||||
|
currentYear = gregorianYear;
|
||||||
|
currentMonth = gregorianMonth;
|
||||||
|
} else if (currentYear === 0 && currentMonth === 0) {
|
||||||
|
currentYear = gregorianYear;
|
||||||
|
currentMonth = gregorianMonth;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gregorianYear === currentYear && gregorianMonth === currentMonth) {
|
||||||
|
currentMonthChineseDays.push(chineseDay.toLowerCase());
|
||||||
|
currentMonthSolarTermNames.push(solarTermName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allMonthChineseDays[`${currentYear}-${currentMonth}`] = currentMonthChineseDays;
|
||||||
|
allMonthSolarTermNames[`${currentYear}-${currentMonth}`] = currentMonthSolarTermNames;
|
||||||
|
|
||||||
|
for (const yearMonth in allMonthChineseDays) {
|
||||||
|
test(`returns correct chinese all dates in month for ${yearMonth}`, () => {
|
||||||
|
const [yearStr, monthStr] = yearMonth.split('-');
|
||||||
|
const year = parseInt(yearStr);
|
||||||
|
const month = parseInt(monthStr);
|
||||||
|
const expectedChineseMonthOrDays = allMonthChineseDays[yearMonth];
|
||||||
|
const expectedSolarTermNames = allMonthSolarTermNames[yearMonth];
|
||||||
|
|
||||||
|
const actualChineseDates: ChineseYearMonthDayInfo[] | undefined = getChineseYearMonthAllDayInfos({
|
||||||
|
year: year,
|
||||||
|
month1base: month
|
||||||
|
}, localeData);
|
||||||
|
|
||||||
|
expect(actualChineseDates).toBeDefined();
|
||||||
|
|
||||||
|
if (actualChineseDates) {
|
||||||
|
for (let i = 0; i < actualChineseDates.length; i++) {
|
||||||
|
const actualChineseDate = actualChineseDates[i];
|
||||||
|
const chineseMonthOrDay: string | undefined = actualChineseDate?.day === 1 ? `${actualChineseDate?.month}${ordinalSuffix[actualChineseDate?.month - 1] ?? 'th'} Lunar Month`.toLowerCase() : actualChineseDate?.day.toString();
|
||||||
|
|
||||||
|
expect(actualChineseDate).toBeDefined();
|
||||||
|
expect(chineseMonthOrDay).toBe(expectedChineseMonthOrDays[i]);
|
||||||
|
expect(actualChineseDate?.solarTermName).toBe(expectedSolarTermNames[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getChineseYearMonthDayInfo', () => {
|
||||||
|
const lines: string[] = fs.readFileSync(path.join(__dirname, 'chinese_calendar_all_data.txt'), 'utf8').split('\n');
|
||||||
|
|
||||||
|
for (const line of lines) {
|
||||||
|
if (!line.trim() || line.startsWith('#')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const items = line.split('\t');
|
||||||
|
const gregorianDate = items[0];
|
||||||
|
const gregorianDateItems = gregorianDate.split('/');
|
||||||
|
const gregorianYear = parseInt(gregorianDateItems[0]);
|
||||||
|
const gregorianMonth = parseInt(gregorianDateItems[1]);
|
||||||
|
const gregorianDay = parseInt(gregorianDateItems[2]);
|
||||||
|
const expectedChineseMonthOrDay = items[1];
|
||||||
|
const expectedSolarTermName = items.length > 3 ? items[3] : '';
|
||||||
|
|
||||||
|
test(`returns correct chinese date for ${gregorianDate}`, () => {
|
||||||
|
const actualChineseDate: ChineseYearMonthDayInfo | undefined = getChineseYearMonthDayInfo({
|
||||||
|
year: gregorianYear,
|
||||||
|
month: gregorianMonth,
|
||||||
|
day: gregorianDay
|
||||||
|
}, localeData);
|
||||||
|
const actualChineseMonthOrDay: string | undefined = actualChineseDate?.day === 1 ? `${actualChineseDate?.month}${ordinalSuffix[actualChineseDate?.month - 1] ?? 'th'} Lunar Month`.toLowerCase() : actualChineseDate?.day.toString();
|
||||||
|
|
||||||
|
expect(actualChineseDate).toBeDefined();
|
||||||
|
expect(actualChineseMonthOrDay).toBe(expectedChineseMonthOrDay.toLowerCase());
|
||||||
|
expect(actualChineseDate?.solarTermName).toBe(expectedSolarTermName);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,431 @@
|
|||||||
|
import {
|
||||||
|
SUPPORTED_MIN_YEAR,
|
||||||
|
SUPPORTED_MAX_YEAR,
|
||||||
|
CHINESE_CALENDAR_FIRST_DAY_GREGORIAN_YEAR,
|
||||||
|
CHINESE_CALENDAR_FIRST_DAY_GREGORIAN_MONTH,
|
||||||
|
CHINESE_CALENDAR_FIRST_DAY_GREGORIAN_DAY,
|
||||||
|
CHINESE_YEAR_DATA,
|
||||||
|
GREGORIAN_YEAR_CHINESE_SOLAR_TERMS_DATA
|
||||||
|
} from './chinese_calendar_data.ts';
|
||||||
|
|
||||||
|
import type { ChineseCalendarLocaleData } from '@/core/calendar.ts';
|
||||||
|
import type { Year1BasedMonth, YearMonthDay, CalendarAlternateDate } from '@/core/datetime.ts';
|
||||||
|
|
||||||
|
import { getGregorianCalendarYearMonthDays, getDayDifference } from '../datetime.ts';
|
||||||
|
|
||||||
|
const CHINESE_CALENDAR_MONTH_COUNT: number = 12;
|
||||||
|
const CHINESE_CALENDAR_BIG_MONTH_DAYS: ChineseDayCount = 30;
|
||||||
|
const CHINESE_CALENDAR_SMALL_MONTH_DAYS: ChineseDayCount = 29;
|
||||||
|
|
||||||
|
const CHINESE_YEAR_INFOS: ChineseCalendarYearInfo[] = initChineseYearInfos();
|
||||||
|
|
||||||
|
interface ChineseYearMonthDay {
|
||||||
|
readonly year: number;
|
||||||
|
readonly month: ChineseMonthValue;
|
||||||
|
readonly day: ChineseDayValue;
|
||||||
|
readonly isLeapMonth: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ChineseCalendarYearInfo {
|
||||||
|
readonly year: number;
|
||||||
|
readonly totalDays: number;
|
||||||
|
readonly firstDayGregorianMonth: number;
|
||||||
|
readonly firstDayGregorianDay: number;
|
||||||
|
readonly normalMonthDays: ChineseDayCount[];
|
||||||
|
readonly leapMonth?: ChineseMonthValue;
|
||||||
|
readonly leapMonthDays?: ChineseDayCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ChineseMonthValue = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12; // 1-12
|
||||||
|
export type ChineseDayValue = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30; // 1-30
|
||||||
|
export type ChineseDayCount = 29 | 30; // 1-29 or 1-30
|
||||||
|
|
||||||
|
export interface ChineseYearMonthDayInfo extends ChineseYearMonthDay {
|
||||||
|
readonly gregorianYear: number;
|
||||||
|
readonly gregorianMonth: number;
|
||||||
|
readonly gregorianDay: number;
|
||||||
|
readonly year: number;
|
||||||
|
readonly month: ChineseMonthValue;
|
||||||
|
readonly day: ChineseDayValue;
|
||||||
|
readonly displayYear: string;
|
||||||
|
readonly displayMonth: string;
|
||||||
|
readonly displayDay: string;
|
||||||
|
readonly isLeapMonth: boolean;
|
||||||
|
readonly solarTermName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function initChineseYearInfos(): ChineseCalendarYearInfo[] {
|
||||||
|
const ret: ChineseCalendarYearInfo[] = [];
|
||||||
|
const gregorianDate: Date = new Date(CHINESE_CALENDAR_FIRST_DAY_GREGORIAN_YEAR, CHINESE_CALENDAR_FIRST_DAY_GREGORIAN_MONTH - 1, CHINESE_CALENDAR_FIRST_DAY_GREGORIAN_DAY);
|
||||||
|
|
||||||
|
for (let year = SUPPORTED_MIN_YEAR; year <= SUPPORTED_MAX_YEAR; year++) {
|
||||||
|
const yearData = CHINESE_YEAR_DATA[year - SUPPORTED_MIN_YEAR];
|
||||||
|
|
||||||
|
if (!yearData) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
const allNormalMonthBigMonthBits: number = yearData >> 5;
|
||||||
|
const leapMonth: number = (yearData >> 1) & 0xF;
|
||||||
|
|
||||||
|
let normalMonthDays: ChineseDayCount[] = [];
|
||||||
|
let leapMonthDays: ChineseDayCount | undefined = undefined;
|
||||||
|
let remainNormalMonthBigMonthBits: number = allNormalMonthBigMonthBits;
|
||||||
|
let totalDays: number = 0;
|
||||||
|
|
||||||
|
for (let i = 12; i >= 1; i--) {
|
||||||
|
const isBigMonth = (remainNormalMonthBigMonthBits & 0x1) === 1;
|
||||||
|
remainNormalMonthBigMonthBits = remainNormalMonthBigMonthBits >> 1;
|
||||||
|
|
||||||
|
if (isBigMonth) {
|
||||||
|
normalMonthDays.push(CHINESE_CALENDAR_BIG_MONTH_DAYS);
|
||||||
|
totalDays += CHINESE_CALENDAR_BIG_MONTH_DAYS;
|
||||||
|
} else {
|
||||||
|
normalMonthDays.push(CHINESE_CALENDAR_SMALL_MONTH_DAYS);
|
||||||
|
totalDays += CHINESE_CALENDAR_SMALL_MONTH_DAYS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (leapMonth > 0) {
|
||||||
|
leapMonthDays = ((yearData & 0x1) === 1) ? CHINESE_CALENDAR_BIG_MONTH_DAYS : CHINESE_CALENDAR_SMALL_MONTH_DAYS;
|
||||||
|
totalDays += leapMonthDays;
|
||||||
|
}
|
||||||
|
|
||||||
|
normalMonthDays = normalMonthDays.reverse();
|
||||||
|
|
||||||
|
const chineseYearInfo: ChineseCalendarYearInfo = {
|
||||||
|
year: year,
|
||||||
|
totalDays: totalDays,
|
||||||
|
firstDayGregorianMonth: gregorianDate.getMonth() + 1,
|
||||||
|
firstDayGregorianDay: gregorianDate.getDate(),
|
||||||
|
normalMonthDays: normalMonthDays,
|
||||||
|
leapMonth: leapMonth > 0 ? (leapMonth as ChineseMonthValue) : undefined,
|
||||||
|
leapMonthDays: leapMonthDays
|
||||||
|
};
|
||||||
|
|
||||||
|
gregorianDate.setDate(gregorianDate.getDate() + totalDays);
|
||||||
|
ret.push(chineseYearInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getChineseNumber(num: number, localeData: ChineseCalendarLocaleData): string {
|
||||||
|
if (num < 0) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
const zeroDigitCharCode = '0'.charCodeAt(0);
|
||||||
|
|
||||||
|
return num.toString().split('').map(ch => {
|
||||||
|
const digit = ch.charCodeAt(0) - zeroDigitCharCode;
|
||||||
|
|
||||||
|
if (digit < 0 || digit > 9) {
|
||||||
|
return ch;
|
||||||
|
} else {
|
||||||
|
return localeData.numerals[digit];
|
||||||
|
}
|
||||||
|
}).join('');
|
||||||
|
}
|
||||||
|
|
||||||
|
function getChineseYearInfo(year: number): ChineseCalendarYearInfo | undefined {
|
||||||
|
if (year < SUPPORTED_MIN_YEAR || year > SUPPORTED_MAX_YEAR) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CHINESE_YEAR_INFOS[year - SUPPORTED_MIN_YEAR];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSolarTermDays(gregorianYear: number, gregorianMonth: number): [number, number, number, number] {
|
||||||
|
if (gregorianYear < SUPPORTED_MIN_YEAR || gregorianYear > SUPPORTED_MAX_YEAR || gregorianMonth < 1 || gregorianMonth > 12) {
|
||||||
|
return [0, 0, 0, 0];
|
||||||
|
}
|
||||||
|
|
||||||
|
const yearIndexInSolarTermData = gregorianYear - SUPPORTED_MIN_YEAR;
|
||||||
|
const solarTerms = GREGORIAN_YEAR_CHINESE_SOLAR_TERMS_DATA[yearIndexInSolarTermData];
|
||||||
|
|
||||||
|
if (!solarTerms) {
|
||||||
|
return [0, 0, 0, 0];
|
||||||
|
}
|
||||||
|
|
||||||
|
const monthIndexInSolarTermData = (gregorianMonth - 1) * 2;
|
||||||
|
const firstTermDayChar = solarTerms.charAt(monthIndexInSolarTermData);
|
||||||
|
const secondTermDayChar = solarTerms.charAt(monthIndexInSolarTermData + 1);
|
||||||
|
let firstTermDay = 0;
|
||||||
|
let firstTermIndex = 0;
|
||||||
|
let secondTermDay = 0;
|
||||||
|
let secondTermIndex = 0;
|
||||||
|
|
||||||
|
if (firstTermDayChar) {
|
||||||
|
firstTermDay = parseInt(firstTermDayChar, 36);
|
||||||
|
firstTermIndex = monthIndexInSolarTermData;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (secondTermDayChar) {
|
||||||
|
secondTermDay = parseInt(secondTermDayChar, 36);
|
||||||
|
secondTermIndex = monthIndexInSolarTermData + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [firstTermDay, firstTermIndex, secondTermDay, secondTermIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSolarTermName(gregorianDate: YearMonthDay, localeData: ChineseCalendarLocaleData): string {
|
||||||
|
if (localeData == null || !localeData.solarTermNames) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
const [firstTermDay, firstTermIndex, secondTermDay, secondTermIndex] = getSolarTermDays(gregorianDate.year, gregorianDate.month);
|
||||||
|
|
||||||
|
if (firstTermDay > 0 && firstTermDay === gregorianDate.day) {
|
||||||
|
return localeData.solarTermNames[firstTermIndex];
|
||||||
|
} else if (secondTermDay > 0 && secondTermDay === gregorianDate.day) {
|
||||||
|
return localeData.solarTermNames[secondTermIndex];
|
||||||
|
} else {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getChineseDate(yearMonthDay: YearMonthDay): ChineseYearMonthDay | undefined {
|
||||||
|
if (yearMonthDay.year < SUPPORTED_MIN_YEAR || yearMonthDay.year > SUPPORTED_MAX_YEAR || yearMonthDay.month < 1 || yearMonthDay.month > 12) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const chineseYearInfo = getChineseYearInfo(yearMonthDay.year);
|
||||||
|
|
||||||
|
if (!chineseYearInfo) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
let gregorianYear: number = 0;
|
||||||
|
let chineseMonth: ChineseMonthValue = 1;
|
||||||
|
let chineseDay: ChineseDayValue = 1;
|
||||||
|
|
||||||
|
if (chineseYearInfo.firstDayGregorianMonth < yearMonthDay.month) {
|
||||||
|
gregorianYear = yearMonthDay.year;
|
||||||
|
} else if (chineseYearInfo.firstDayGregorianMonth === yearMonthDay.month && chineseYearInfo.firstDayGregorianDay <= yearMonthDay.day) {
|
||||||
|
gregorianYear = yearMonthDay.year;
|
||||||
|
} else {
|
||||||
|
gregorianYear = yearMonthDay.year - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentChineseYearInfo = getChineseYearInfo(gregorianYear);
|
||||||
|
|
||||||
|
if (!currentChineseYearInfo) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gregorianYear === yearMonthDay.year && yearMonthDay.month === currentChineseYearInfo.firstDayGregorianMonth && yearMonthDay.day === currentChineseYearInfo.firstDayGregorianDay) {
|
||||||
|
return {
|
||||||
|
year: gregorianYear,
|
||||||
|
month: chineseMonth,
|
||||||
|
day: chineseDay,
|
||||||
|
isLeapMonth: currentChineseYearInfo.leapMonth === 1
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const dayDifference: number = getDayDifference({
|
||||||
|
year: currentChineseYearInfo.year,
|
||||||
|
month: currentChineseYearInfo.firstDayGregorianMonth,
|
||||||
|
day: currentChineseYearInfo.firstDayGregorianDay
|
||||||
|
}, yearMonthDay);
|
||||||
|
|
||||||
|
if (dayDifference < 0) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
let remainDays: number = dayDifference;
|
||||||
|
|
||||||
|
while (remainDays > 0) {
|
||||||
|
let currentMonthDays: number | undefined = currentChineseYearInfo.normalMonthDays[chineseMonth - 1];
|
||||||
|
|
||||||
|
if (!currentMonthDays) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
let isLeapMonth: boolean = false;
|
||||||
|
let skipNormalMonth: boolean = false;
|
||||||
|
let skipLeapMonth: boolean = false;
|
||||||
|
|
||||||
|
if (remainDays >= currentMonthDays) {
|
||||||
|
remainDays -= currentMonthDays;
|
||||||
|
skipNormalMonth = true;
|
||||||
|
} else {
|
||||||
|
chineseDay += remainDays;
|
||||||
|
remainDays = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chineseDay > currentMonthDays) {
|
||||||
|
chineseDay = currentMonthDays - chineseDay;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skipNormalMonth && remainDays > 0 && chineseMonth === currentChineseYearInfo.leapMonth) {
|
||||||
|
currentMonthDays = currentChineseYearInfo.leapMonthDays || 0;
|
||||||
|
isLeapMonth = true;
|
||||||
|
|
||||||
|
if (remainDays >= currentMonthDays) {
|
||||||
|
remainDays -= currentMonthDays;
|
||||||
|
skipLeapMonth = true;
|
||||||
|
} else {
|
||||||
|
chineseDay += remainDays;
|
||||||
|
remainDays = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chineseDay > currentMonthDays) {
|
||||||
|
chineseDay = currentMonthDays - chineseDay;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skipLeapMonth) {
|
||||||
|
chineseMonth++;
|
||||||
|
} else if (skipNormalMonth && !isLeapMonth) {
|
||||||
|
if (chineseMonth === currentChineseYearInfo.leapMonth) {
|
||||||
|
isLeapMonth = true;
|
||||||
|
} else {
|
||||||
|
chineseMonth++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chineseMonth > CHINESE_CALENDAR_MONTH_COUNT) {
|
||||||
|
chineseMonth = chineseMonth - CHINESE_CALENDAR_MONTH_COUNT;
|
||||||
|
gregorianYear++;
|
||||||
|
|
||||||
|
if (gregorianYear > SUPPORTED_MAX_YEAR) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remainDays === 0) {
|
||||||
|
return {
|
||||||
|
year: gregorianYear,
|
||||||
|
month: chineseMonth as ChineseMonthValue,
|
||||||
|
day: chineseDay as ChineseDayValue,
|
||||||
|
isLeapMonth: isLeapMonth
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildChineseYearMonthDayInfo(gregorianDate: YearMonthDay, chineseDate: ChineseYearMonthDay, localeData: ChineseCalendarLocaleData): ChineseYearMonthDayInfo {
|
||||||
|
const chineseYearMonthDayInfo: ChineseYearMonthDayInfo = {
|
||||||
|
gregorianYear: gregorianDate.year,
|
||||||
|
gregorianMonth: gregorianDate.month,
|
||||||
|
gregorianDay: gregorianDate.day,
|
||||||
|
year: chineseDate.year,
|
||||||
|
month: chineseDate.month,
|
||||||
|
day: chineseDate.day,
|
||||||
|
displayYear: getChineseNumber(chineseDate.year, localeData),
|
||||||
|
displayMonth: (chineseDate.isLeapMonth ? localeData.leapMonthPrefix : '') + localeData.monthNames[chineseDate.month - 1],
|
||||||
|
displayDay: localeData.dayNames[chineseDate.day - 1],
|
||||||
|
isLeapMonth: chineseDate.isLeapMonth,
|
||||||
|
solarTermName: getSolarTermName(gregorianDate, localeData)
|
||||||
|
};
|
||||||
|
|
||||||
|
return chineseYearMonthDayInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getChineseYearMonthAllDayInfos(yearMonth: Year1BasedMonth, localeData: ChineseCalendarLocaleData): ChineseYearMonthDayInfo[] | undefined {
|
||||||
|
const monthFirstDay: YearMonthDay = {
|
||||||
|
year: yearMonth.year,
|
||||||
|
month: yearMonth.month1base,
|
||||||
|
day: 1
|
||||||
|
};
|
||||||
|
|
||||||
|
const chineseFirstDate: ChineseYearMonthDay | undefined = getChineseDate(monthFirstDay);
|
||||||
|
|
||||||
|
if (!chineseFirstDate) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const chineseYearInfo = getChineseYearInfo(chineseFirstDate.year);
|
||||||
|
|
||||||
|
if (!chineseYearInfo) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const allDayInfos: ChineseYearMonthDayInfo[] = [];
|
||||||
|
allDayInfos.push(buildChineseYearMonthDayInfo(monthFirstDay, chineseFirstDate, localeData));
|
||||||
|
|
||||||
|
const gregorianDate: Date = new Date(monthFirstDay.year, monthFirstDay.month - 1, monthFirstDay.day);
|
||||||
|
let chineseYear: number = chineseFirstDate.year;
|
||||||
|
let chineseMonth: ChineseMonthValue = chineseFirstDate.month;
|
||||||
|
let chineseDay: ChineseDayValue = chineseFirstDate.day;
|
||||||
|
let chineseLeapMonth: boolean = chineseFirstDate.isLeapMonth;
|
||||||
|
let remainDays: number = getGregorianCalendarYearMonthDays(yearMonth) - 1;
|
||||||
|
|
||||||
|
while (remainDays > 0) {
|
||||||
|
const chineseMonthDays: number | undefined = chineseLeapMonth ? chineseYearInfo.leapMonthDays : chineseYearInfo.normalMonthDays[chineseMonth - 1];
|
||||||
|
|
||||||
|
if (!chineseMonthDays) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
gregorianDate.setDate(gregorianDate.getDate() + 1);
|
||||||
|
chineseDay++;
|
||||||
|
remainDays--;
|
||||||
|
|
||||||
|
if (chineseDay > chineseMonthDays) {
|
||||||
|
chineseDay = chineseDay - chineseMonthDays;
|
||||||
|
|
||||||
|
if (chineseYearInfo.leapMonth === chineseMonth && !chineseLeapMonth) {
|
||||||
|
chineseLeapMonth = true;
|
||||||
|
} else {
|
||||||
|
chineseMonth++;
|
||||||
|
|
||||||
|
if (chineseMonth > CHINESE_CALENDAR_MONTH_COUNT) {
|
||||||
|
chineseMonth = chineseMonth - CHINESE_CALENDAR_MONTH_COUNT;
|
||||||
|
chineseYear++;
|
||||||
|
|
||||||
|
if (chineseYear > SUPPORTED_MAX_YEAR) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allDayInfos.push(buildChineseYearMonthDayInfo({
|
||||||
|
year: gregorianDate.getFullYear(),
|
||||||
|
month: gregorianDate.getMonth() + 1,
|
||||||
|
day: gregorianDate.getDate()
|
||||||
|
}, {
|
||||||
|
year: chineseYear,
|
||||||
|
month: chineseMonth as ChineseMonthValue,
|
||||||
|
day: chineseDay as ChineseDayValue,
|
||||||
|
isLeapMonth: chineseLeapMonth
|
||||||
|
}, localeData));
|
||||||
|
}
|
||||||
|
|
||||||
|
return allDayInfos;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getChineseYearMonthDayInfo(yearMonthDay: YearMonthDay, localeData: ChineseCalendarLocaleData): ChineseYearMonthDayInfo | undefined {
|
||||||
|
const chineseDate: ChineseYearMonthDay | undefined = getChineseDate(yearMonthDay);
|
||||||
|
|
||||||
|
if (!chineseDate) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buildChineseYearMonthDayInfo(yearMonthDay, chineseDate, localeData);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getChineseCalendarAlternateDisplayDate(chineseDate: ChineseYearMonthDayInfo): CalendarAlternateDate {
|
||||||
|
let displayDate = chineseDate.displayDay;
|
||||||
|
|
||||||
|
if (chineseDate.day === 1) {
|
||||||
|
displayDate = chineseDate.displayMonth;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chineseDate.solarTermName) {
|
||||||
|
displayDate = chineseDate.solarTermName;
|
||||||
|
}
|
||||||
|
|
||||||
|
const alternateDate: CalendarAlternateDate = {
|
||||||
|
year: chineseDate.gregorianYear,
|
||||||
|
month: chineseDate.gregorianMonth,
|
||||||
|
day: chineseDate.gregorianDay,
|
||||||
|
displayDate: displayDate
|
||||||
|
};
|
||||||
|
|
||||||
|
return alternateDate;
|
||||||
|
}
|
||||||
@@ -0,0 +1,455 @@
|
|||||||
|
// Chinese Calendar data from Hong Kong Observatory: https://www.hko.gov.hk/tc/gts/time/conversion1_text.htm
|
||||||
|
// The following bash scripts is about generating compacted Chinese calendar data
|
||||||
|
/*
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# fetch calendar date from Hong Kong Observatory
|
||||||
|
for i in {1999..2100};
|
||||||
|
do
|
||||||
|
wget "https://my.weather.gov.hk/en/gts/time/calendar/text/files/T${i}e.txt";
|
||||||
|
done
|
||||||
|
|
||||||
|
# generate the compacted data
|
||||||
|
for i in {1999..2100};
|
||||||
|
do
|
||||||
|
if ! [ -f "T${i}e.txt" ]; then
|
||||||
|
echo "Error: file T${i}e.txt not exists";
|
||||||
|
exit 1;
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat T${i}e.txt;
|
||||||
|
done | grep -v 'Gregorian-Lunar Calendar Conversion Table' | awk '
|
||||||
|
function rtrim(s) {
|
||||||
|
sub(/[ \t]+$/, "", s);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
BEGIN {
|
||||||
|
# constants
|
||||||
|
FIRST_YEAR = 1999;
|
||||||
|
LAST_YEAR = 2100;
|
||||||
|
GREGORIAN_CALENDAR_1999_1_1_CHINESE_YEAR = 1998;
|
||||||
|
GREGORIAN_CALENDAR_1999_1_1_CHINESE_MONTH = 11;
|
||||||
|
CHINESE_CALENDAR_MONTH_COUNT = 12;
|
||||||
|
CHINESE_CALENDAR_BIG_MONTH_DAYS = 30;
|
||||||
|
CHINESE_CALENDAR_SOLAR_TERMS_COUNT = 24;
|
||||||
|
SINGLE_QUOTE_CHAR = 39;
|
||||||
|
split("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", BASE36_CHARS, "");
|
||||||
|
SOLAR_TERMS_INDEX["Moderate Cold"] = 1;
|
||||||
|
SOLAR_TERMS_INDEX["Severe Cold"] = 2;
|
||||||
|
SOLAR_TERMS_INDEX["Spring Commences"] = 3;
|
||||||
|
SOLAR_TERMS_INDEX["Spring Showers"] = 4;
|
||||||
|
SOLAR_TERMS_INDEX["Insects Waken"] = 5;
|
||||||
|
SOLAR_TERMS_INDEX["Vernal Equinox"] = 6;
|
||||||
|
SOLAR_TERMS_INDEX["Bright & Clear"] = 7;
|
||||||
|
SOLAR_TERMS_INDEX["Corn Rain"] = 8;
|
||||||
|
SOLAR_TERMS_INDEX["Summer Commences"] = 9;
|
||||||
|
SOLAR_TERMS_INDEX["Corn Forms"] = 10;
|
||||||
|
SOLAR_TERMS_INDEX["Corn on Ear"] = 11;
|
||||||
|
SOLAR_TERMS_INDEX["Summer Solstice"] = 12;
|
||||||
|
SOLAR_TERMS_INDEX["Moderate Heat"] = 13;
|
||||||
|
SOLAR_TERMS_INDEX["Great Heat"] = 14;
|
||||||
|
SOLAR_TERMS_INDEX["Autumn Commences"] = 15;
|
||||||
|
SOLAR_TERMS_INDEX["End of Heat"] = 16;
|
||||||
|
SOLAR_TERMS_INDEX["White Dew"] = 17;
|
||||||
|
SOLAR_TERMS_INDEX["Autumnal Equinox"] = 18;
|
||||||
|
SOLAR_TERMS_INDEX["Cold Dew"] = 19;
|
||||||
|
SOLAR_TERMS_INDEX["Frost"] = 20;
|
||||||
|
SOLAR_TERMS_INDEX["Winter Commences"] = 21;
|
||||||
|
SOLAR_TERMS_INDEX["Light Snow"] = 22;
|
||||||
|
SOLAR_TERMS_INDEX["Heavy Snow"] = 23;
|
||||||
|
SOLAR_TERMS_INDEX["Winter Solstice"] = 24;
|
||||||
|
|
||||||
|
# variables
|
||||||
|
errorMessage = "";
|
||||||
|
chineseYear = GREGORIAN_CALENDAR_1999_1_1_CHINESE_YEAR;
|
||||||
|
chineseMonth = GREGORIAN_CALENDAR_1999_1_1_CHINESE_MONTH;
|
||||||
|
chineseDay = 0;
|
||||||
|
chineseLeapMonth = 0;
|
||||||
|
firstChineseYearGregorianYear = FIRST_YEAR;
|
||||||
|
firstChineseYearGregorianMonth = 0;
|
||||||
|
firstChineseYearGregorianDay = 0;
|
||||||
|
column1StartIndex = 1;
|
||||||
|
column1Length = 15;
|
||||||
|
column2StartIndex = 16;
|
||||||
|
column2Length = 20;
|
||||||
|
column3StartIndex = 36;
|
||||||
|
column3Length = 15;
|
||||||
|
column4StartIndex = 51;
|
||||||
|
column4Length = 20;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
# check whether the provided data is invalid
|
||||||
|
if (index($0, "Error: ") == 1 || errorMessage != "") {
|
||||||
|
errorMessage = $0;
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
# calculate the length of each column from the header line
|
||||||
|
if (index($0, "Gregorian date") == 1) {
|
||||||
|
column2StartIndex = index($0, "Lunar date");
|
||||||
|
column1Length = column2StartIndex - column1StartIndex;
|
||||||
|
column3StartIndex = index($0, "Day-of-week");
|
||||||
|
column2Length = column3StartIndex - column2StartIndex;
|
||||||
|
column4StartIndex = index($0, "Solar terms");
|
||||||
|
column3Length = column4StartIndex - column3StartIndex;
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
# parse the gregorian date
|
||||||
|
col1 = rtrim(substr($0, column1StartIndex, column1Length));
|
||||||
|
col2 = rtrim(substr($0, column2StartIndex, column2Length));
|
||||||
|
col3 = rtrim(substr($0, column3StartIndex, column3Length));
|
||||||
|
col4 = rtrim(substr($0, column4StartIndex, column4Length));
|
||||||
|
|
||||||
|
split(col1, gregorianDate, "/");
|
||||||
|
gregorianYear = int(gregorianDate[1]);
|
||||||
|
gregorianMonth = int(gregorianDate[2]);
|
||||||
|
gregorianDay = int(gregorianDate[3]);
|
||||||
|
|
||||||
|
# parse Chinese day and calculate the Chinese year and month
|
||||||
|
nextChineseYear = chineseYear;
|
||||||
|
nextChineseMonth = chineseMonth;
|
||||||
|
nextChineseDay = chineseDay;
|
||||||
|
|
||||||
|
if (index(col2, " Lunar month") > 0) {
|
||||||
|
nextChineseMonth = substr(col2, 1, (index(col2, " Lunar month") - 3));
|
||||||
|
nextChineseDay = 1;
|
||||||
|
|
||||||
|
if (nextChineseMonth == 1) {
|
||||||
|
nextChineseYear++;
|
||||||
|
}
|
||||||
|
} else if (index(col2, " Lunar Month") > 0) {
|
||||||
|
nextChineseMonth = substr(col2, 1, (index(col2, " Lunar Month") - 3));
|
||||||
|
nextChineseDay = 1;
|
||||||
|
|
||||||
|
if (nextChineseMonth == 1) {
|
||||||
|
nextChineseYear++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
nextChineseDay = col2;
|
||||||
|
}
|
||||||
|
|
||||||
|
# store the previous month info
|
||||||
|
if (nextChineseDay == 1) {
|
||||||
|
if (chineseLeapMonth == 0) {
|
||||||
|
chineseMonthDayCountMap[chineseYear][chineseMonth] = chineseDay;
|
||||||
|
} else {
|
||||||
|
chineseLeapMonthMap[chineseYear] = chineseMonth;
|
||||||
|
chineseLeapMonthDayCount[chineseYear] = chineseDay;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextChineseMonth == chineseMonth) {
|
||||||
|
chineseLeapMonth = 1;
|
||||||
|
} else {
|
||||||
|
chineseLeapMonth = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextChineseDay == 1 && nextChineseMonth == 1 && nextChineseYear == FIRST_YEAR && chineseLeapMonth == 0) {
|
||||||
|
firstChineseYearGregorianMonth = gregorianMonth;
|
||||||
|
firstChineseYearGregorianDay = gregorianDay;
|
||||||
|
}
|
||||||
|
|
||||||
|
gregorianDayBase36 = BASE36_CHARS[gregorianDay + 1];
|
||||||
|
solarTermIndex = SOLAR_TERMS_INDEX[col4];
|
||||||
|
solarTermsMap[gregorianYear][solarTermIndex] = gregorianDayBase36;
|
||||||
|
|
||||||
|
chineseYear = nextChineseYear;
|
||||||
|
chineseMonth = nextChineseMonth;
|
||||||
|
chineseDay = nextChineseDay;
|
||||||
|
}
|
||||||
|
END {
|
||||||
|
if (errorMessage != "") {
|
||||||
|
print errorMessage;
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
# output contants
|
||||||
|
printf "export const SUPPORTED_MIN_YEAR: number = %s;\n", FIRST_YEAR;
|
||||||
|
printf "export const SUPPORTED_MAX_YEAR: number = %s;\n", LAST_YEAR;
|
||||||
|
print "";
|
||||||
|
printf "export const CHINESE_CALENDAR_FIRST_DAY_GREGORIAN_YEAR: number = %s;\n", firstChineseYearGregorianYear;
|
||||||
|
printf "export const CHINESE_CALENDAR_FIRST_DAY_GREGORIAN_MONTH: number = %s;\n", firstChineseYearGregorianMonth;
|
||||||
|
printf "export const CHINESE_CALENDAR_FIRST_DAY_GREGORIAN_DAY: number = %s;\n", firstChineseYearGregorianDay;
|
||||||
|
print "";
|
||||||
|
|
||||||
|
# output compacted data table of chinese years
|
||||||
|
print "export const CHINESE_YEAR_DATA: number[] = [";
|
||||||
|
for (year = FIRST_YEAR; year <= LAST_YEAR; year++) {
|
||||||
|
printf " "
|
||||||
|
|
||||||
|
# each element is a hexadecimal representing a 17-bit integer:
|
||||||
|
# - bits 0-11: month days from month 1 to month 12 (0 means 29 days, 1 means 30 days)
|
||||||
|
# - bits 12-15: leap month (0 means no leap month, 1-12 means the leap month)
|
||||||
|
# - bit 16: leap month days (0 means 29 days, 1 means 30 days)
|
||||||
|
data = 0;
|
||||||
|
|
||||||
|
for (month = 1; month <= CHINESE_CALENDAR_MONTH_COUNT; month++) {
|
||||||
|
dayCount = chineseMonthDayCountMap[year][month];
|
||||||
|
bigMonth = 0;
|
||||||
|
|
||||||
|
if (dayCount == CHINESE_CALENDAR_BIG_MONTH_DAYS) {
|
||||||
|
bigMonth = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = lshift(data, 1);
|
||||||
|
data = or(data, bigMonth);
|
||||||
|
}
|
||||||
|
|
||||||
|
leapMonth = chineseLeapMonthMap[year];
|
||||||
|
|
||||||
|
if (leapMonth == "") {
|
||||||
|
leapMonth = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = lshift(data, 4);
|
||||||
|
data = or(data, leapMonth);
|
||||||
|
|
||||||
|
data = lshift(data, 1);
|
||||||
|
if (leapMonth > 0) {
|
||||||
|
bigMonth = 0;
|
||||||
|
|
||||||
|
if (chineseLeapMonthDayCount[year] == CHINESE_CALENDAR_BIG_MONTH_DAYS) {
|
||||||
|
bigMonth = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = or(data, bigMonth);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf "0x%x, // %s\n", data, year;
|
||||||
|
}
|
||||||
|
print "];";
|
||||||
|
|
||||||
|
print "";
|
||||||
|
|
||||||
|
# output compacted data table of solar terms
|
||||||
|
# each element is a string of 24 base-36 (0-9A-Z) characters, each character represents the day in month (1-based) of the corresponding solar term
|
||||||
|
print "export const GREGORIAN_YEAR_CHINESE_SOLAR_TERMS_DATA: string[] = [";
|
||||||
|
for (year = FIRST_YEAR; year <= LAST_YEAR; year++) {
|
||||||
|
printf " %c", SINGLE_QUOTE_CHAR;
|
||||||
|
for (i = 1; i <= CHINESE_CALENDAR_SOLAR_TERMS_COUNT; i++) {
|
||||||
|
printf solarTermsMap[year][i];
|
||||||
|
}
|
||||||
|
printf "%c, // %s\n", SINGLE_QUOTE_CHAR, year;
|
||||||
|
}
|
||||||
|
print "];";
|
||||||
|
}'
|
||||||
|
*/
|
||||||
|
|
||||||
|
// The following lines are generated by the above bash scripts
|
||||||
|
export const SUPPORTED_MIN_YEAR: number = 1999;
|
||||||
|
export const SUPPORTED_MAX_YEAR: number = 2100;
|
||||||
|
|
||||||
|
export const CHINESE_CALENDAR_FIRST_DAY_GREGORIAN_YEAR: number = 1999;
|
||||||
|
export const CHINESE_CALENDAR_FIRST_DAY_GREGORIAN_MONTH: number = 2;
|
||||||
|
export const CHINESE_CALENDAR_FIRST_DAY_GREGORIAN_DAY: number = 16;
|
||||||
|
|
||||||
|
export const CHINESE_YEAR_DATA: number[] = [
|
||||||
|
0x125c0, // 1999
|
||||||
|
0x192c0, // 2000
|
||||||
|
0x1b2a8, // 2001
|
||||||
|
0x1a940, // 2002
|
||||||
|
0x1b4a0, // 2003
|
||||||
|
0xeaa4, // 2004
|
||||||
|
0xad40, // 2005
|
||||||
|
0x1576e, // 2006
|
||||||
|
0x4ba0, // 2007
|
||||||
|
0x125a0, // 2008
|
||||||
|
0x1956a, // 2009
|
||||||
|
0x152a0, // 2010
|
||||||
|
0x16940, // 2011
|
||||||
|
0x17548, // 2012
|
||||||
|
0x15aa0, // 2013
|
||||||
|
0xabb2, // 2014
|
||||||
|
0x9740, // 2015
|
||||||
|
0x14b60, // 2016
|
||||||
|
0xa2ed, // 2017
|
||||||
|
0xa560, // 2018
|
||||||
|
0x15260, // 2019
|
||||||
|
0xf2a8, // 2020
|
||||||
|
0xd540, // 2021
|
||||||
|
0x15aa0, // 2022
|
||||||
|
0xb6a4, // 2023
|
||||||
|
0x96c0, // 2024
|
||||||
|
0x14dcc, // 2025
|
||||||
|
0x149c0, // 2026
|
||||||
|
0x1a4c0, // 2027
|
||||||
|
0x1d4ca, // 2028
|
||||||
|
0x1aa60, // 2029
|
||||||
|
0xb540, // 2030
|
||||||
|
0xed46, // 2031
|
||||||
|
0x12da0, // 2032
|
||||||
|
0x95f6, // 2033
|
||||||
|
0x95a0, // 2034
|
||||||
|
0x149a0, // 2035
|
||||||
|
0x1a16d, // 2036
|
||||||
|
0x1a4a0, // 2037
|
||||||
|
0x1aa40, // 2038
|
||||||
|
0x1ba8a, // 2039
|
||||||
|
0x16b40, // 2040
|
||||||
|
0xada0, // 2041
|
||||||
|
0xab64, // 2042
|
||||||
|
0x9360, // 2043
|
||||||
|
0x14aee, // 2044
|
||||||
|
0x14960, // 2045
|
||||||
|
0x154a0, // 2046
|
||||||
|
0x164ab, // 2047
|
||||||
|
0xda40, // 2048
|
||||||
|
0x15b40, // 2049
|
||||||
|
0x96c7, // 2050
|
||||||
|
0x126e0, // 2051
|
||||||
|
0x93f0, // 2052
|
||||||
|
0x92e0, // 2053
|
||||||
|
0xc960, // 2054
|
||||||
|
0xd14d, // 2055
|
||||||
|
0x1d4a0, // 2056
|
||||||
|
0xd540, // 2057
|
||||||
|
0x14d89, // 2058
|
||||||
|
0x155c0, // 2059
|
||||||
|
0x125c0, // 2060
|
||||||
|
0x1a5c6, // 2061
|
||||||
|
0x192c0, // 2062
|
||||||
|
0x1aaae, // 2063
|
||||||
|
0x1a940, // 2064
|
||||||
|
0x1b4a0, // 2065
|
||||||
|
0xbaaa, // 2066
|
||||||
|
0xad40, // 2067
|
||||||
|
0x14da0, // 2068
|
||||||
|
0xaba8, // 2069
|
||||||
|
0xa5a0, // 2070
|
||||||
|
0x15370, // 2071
|
||||||
|
0x152a0, // 2072
|
||||||
|
0x16940, // 2073
|
||||||
|
0x16d4c, // 2074
|
||||||
|
0x15aa0, // 2075
|
||||||
|
0xab40, // 2076
|
||||||
|
0x15748, // 2077
|
||||||
|
0x14b60, // 2078
|
||||||
|
0xa560, // 2079
|
||||||
|
0x164e6, // 2080
|
||||||
|
0xd260, // 2081
|
||||||
|
0xe66e, // 2082
|
||||||
|
0xd540, // 2083
|
||||||
|
0x15aa0, // 2084
|
||||||
|
0x96ab, // 2085
|
||||||
|
0x96c0, // 2086
|
||||||
|
0x14ae0, // 2087
|
||||||
|
0xa9c8, // 2088
|
||||||
|
0x1a2c0, // 2089
|
||||||
|
0x1d2d0, // 2090
|
||||||
|
0x1aa40, // 2091
|
||||||
|
0x1b540, // 2092
|
||||||
|
0xd54d, // 2093
|
||||||
|
0xada0, // 2094
|
||||||
|
0x95c0, // 2095
|
||||||
|
0x153a8, // 2096
|
||||||
|
0x145a0, // 2097
|
||||||
|
0x1a2a0, // 2098
|
||||||
|
0x1e4a4, // 2099
|
||||||
|
0x1aa40, // 2100
|
||||||
|
];
|
||||||
|
|
||||||
|
export const GREGORIAN_YEAR_CHINESE_SOLAR_TERMS_DATA: string[] = [
|
||||||
|
'6K4J6L5K6L6M7N8N8N9O8N7M', // 1999
|
||||||
|
'6L4J5K4K5L5L7M7N7N8N7M7L', // 2000
|
||||||
|
'5K4I5K5K5L5L7N7N7N8N7M7M', // 2001
|
||||||
|
'5K4J6L5K6L6L7N8N8N8N7M7M', // 2002
|
||||||
|
'6K4J6L5K6L6M7N8N8N9O8N7M', // 2003
|
||||||
|
'6L4J5K4K5L5L7M7N7N8N7M7L', // 2004
|
||||||
|
'5K4I5K5K5L5L7N7N7N8N7M7M', // 2005
|
||||||
|
'5K4J6L5K5L6L7N7N8N8N7M7M', // 2006
|
||||||
|
'6K4J6L5K6L6M7N8N8N9O8N7M', // 2007
|
||||||
|
'6L4J5K4K5L5L7M7N7M8N7M7L', // 2008
|
||||||
|
'5K4I5K4K5L5L7N7N7N8N7M7M', // 2009
|
||||||
|
'5K4J6L5K5L6L7N7N8N8N7M7M', // 2010
|
||||||
|
'6K4J6L5K6L6M7N8N8N8O8N7M', // 2011
|
||||||
|
'6L4J5K4K5K5L7M7N7M8N7M7L', // 2012
|
||||||
|
'5K4I5K4K5L5L7M7N7N8N7M7M', // 2013
|
||||||
|
'5K4J6L5K5L6L7N7N8N8N7M7M', // 2014
|
||||||
|
'6K4J6L5K6L6M7N8N8N8O8M7M', // 2015
|
||||||
|
'6K4J5K4J5K5L7M7N7M8N7M7L', // 2016
|
||||||
|
'5K3I5K4K5L5L7M7N7N8N7M7M', // 2017
|
||||||
|
'5K4J5L5K5L6L7N7N8N8N7M7M', // 2018
|
||||||
|
'5K4J6L5K6L6L7N8N8N8O8M7M', // 2019
|
||||||
|
'6K4J5K4J5K5L6M7M7M8N7M7L', // 2020
|
||||||
|
'5K3I5K4K5L5L7M7N7N8N7M7L', // 2021
|
||||||
|
'5K4J5K5K5L6L7N7N7N8N7M7M', // 2022
|
||||||
|
'5K4J6L5K6L6L7N8N8N8O8M7M', // 2023
|
||||||
|
'6K4J5K4J5K5L6M7M7M8N7M6L', // 2024
|
||||||
|
'5K3I5K4K5L5L7M7N7N8N7M7L', // 2025
|
||||||
|
'5K4I5K5K5L5L7N7N7N8N7M7M', // 2026
|
||||||
|
'5K4J6L5K6L6L7N8N8N8N7M7M', // 2027
|
||||||
|
'6K4J5K4J5K5L6M7M7M8N7M6L', // 2028
|
||||||
|
'5K3I5K4K5L5L7M7N7N8N7M7L', // 2029
|
||||||
|
'5K4I5K5K5L5L7N7N7N8N7M7M', // 2030
|
||||||
|
'5K4J6L5K6L6L7N8N8N8N7M7M', // 2031
|
||||||
|
'6K4J5K4J5K5L6M7M7M8N7M6L', // 2032
|
||||||
|
'5K3I5K4K5L5L7M7N7N8N7M7L', // 2033
|
||||||
|
'5K4I5K5K5L5L7N7N7N8N7M7M', // 2034
|
||||||
|
'5K4J6L5K5L6L7N7N8N8N7M7M', // 2035
|
||||||
|
'6K4J5K4J5K5L6M7M7M8N7M6L', // 2036
|
||||||
|
'5K3I5K4K5L5L7M7N7N8N7M7L', // 2037
|
||||||
|
'5K4I5K5K5L5L7N7N7N8N7M7M', // 2038
|
||||||
|
'5K4J6L5K5L6L7N7N8N8N7M7M', // 2039
|
||||||
|
'6K4J5K4J5K5L6M7M7M8N7M6L', // 2040
|
||||||
|
'5K3I5K4K5K5L7M7N7M8N7M7L', // 2041
|
||||||
|
'5K4I5K4K5L5L7N7N7N8N7M7M', // 2042
|
||||||
|
'5K4J6L5K5L6L7N7N8N8N7M7M', // 2043
|
||||||
|
'6K4J5K4J5K5L6M7M7M7N7M6L', // 2044
|
||||||
|
'5K3I5K4J5K5L7M7N7M8N7M7L', // 2045
|
||||||
|
'5K4I5K4K5L5L7M7N7N8N7M7M', // 2046
|
||||||
|
'5K4J6L5K5L6L7N7N8N8N7M7M', // 2047
|
||||||
|
'6K4J5K4J5K5K6M7M7M7N7L6L', // 2048
|
||||||
|
'5J3I5K4J5K5L6M7M7M8N7M7L', // 2049
|
||||||
|
'5K3I5K4K5L5L7M7N7N8N7M7M', // 2050
|
||||||
|
'5K4J5K5K5L6L7N7N7N8N7M7M', // 2051
|
||||||
|
'5K4J5K4J5K5K6M7M7M7N7L6L', // 2052
|
||||||
|
'5J3I5K4J5K5L6M7M7M8N7M7L', // 2053
|
||||||
|
'5K3I5K4K5L5L7M7N7N8N7M7M', // 2054
|
||||||
|
'5K4J5K5K5L5L7N7N7N8N7M7M', // 2055
|
||||||
|
'5K4J5K4J5K5K6M7M7M7N7L6L', // 2056
|
||||||
|
'5J3I5K4J5K5L6M7M7M8N7M6L', // 2057
|
||||||
|
'5K3I5K4K5L5L7M7N7N8N7M7L', // 2058
|
||||||
|
'5K4J5K5K5L5L7N7N7N8N7M7M', // 2059
|
||||||
|
'5K4J5K4J5K5K6M7M7M7M6L6L', // 2060
|
||||||
|
'5J3I5K4J5K5L6M7M7M8N7M6L', // 2061
|
||||||
|
'5K3I5K4K5L5L7M7N7N8N7M7L', // 2062
|
||||||
|
'5K4I5K5K5L5L7N7N7N8N7M7M', // 2063
|
||||||
|
'5K4J5K4J5K5K6M7M7M7M6L6L', // 2064
|
||||||
|
'5J3I5K4J5K5L6M7M7M8N7M6L', // 2065
|
||||||
|
'5K3I5K4K5L5L7M7N7N8N7M7L', // 2066
|
||||||
|
'5K4I5K5K5L5L7N7N7N8N7M7M', // 2067
|
||||||
|
'5K4J5K4J4K5K6M6M7M7M6L6L', // 2068
|
||||||
|
'5J3I5K4J5K5L6M7M7M8N7M6L', // 2069
|
||||||
|
'5K3I5K4K5K5L7M7N7M8N7M7L', // 2070
|
||||||
|
'5K4I5K5K5L5L7N7N7N8N7M7M', // 2071
|
||||||
|
'5K4J5K4J4K5K6M6M7M7M6L6L', // 2072
|
||||||
|
'5J3I5K4J5K5L6M7M7M7N7M6L', // 2073
|
||||||
|
'5K3I5K4K5K5L7M7N7M8N7M7L', // 2074
|
||||||
|
'5K4I5K4K5L5L7M7N7N8N7M7M', // 2075
|
||||||
|
'5K4J5K4J4K5K6M6M7M7M6L6L', // 2076
|
||||||
|
'5J3I5K4J5K5L6M7M7M7N7M6L', // 2077
|
||||||
|
'5K3I5K4J5K5L6M7N7M8N7M7L', // 2078
|
||||||
|
'5K4I5K4K5L5L7M7N7N8N7M7M', // 2079
|
||||||
|
'5K4J5K4J4K5K6M6M7M7M6L6L', // 2080
|
||||||
|
'5J3I5K4J5K5K6M7M7M7N7L6L', // 2081
|
||||||
|
'5K3I5K4J5K5L6M7M7M8N7M7L', // 2082
|
||||||
|
'5K3I5K4K5L5L7M7N7N8N7M7M', // 2083
|
||||||
|
'5K4J4J4J4K5K6M6M6M7M6L6L', // 2084
|
||||||
|
'4J3I5K4J5K5K6M7M7M7N7L6L', // 2085
|
||||||
|
'5J3I5K4J5K5L6M7M7M8N7M7L', // 2086
|
||||||
|
'5K3I5K4K5L5L7M7N7N8N7M7M', // 2087
|
||||||
|
'5K4J4J4J4K4K6M6M6M7M6L6L', // 2088
|
||||||
|
'4J3I5K4J5K5K6M7M7M7N7L6L', // 2089
|
||||||
|
'5J3I5K4J5K5L6M7M7M8N7M6L', // 2090
|
||||||
|
'5K3I5K4K5L5L7M7N7N8N7M7L', // 2091
|
||||||
|
'5K4J4J4J4K4K6M6M6M7M6L6L', // 2092
|
||||||
|
'4J3I5K4J5K5K6M7M7M7M6L6L', // 2093
|
||||||
|
'5J3I5K4J5K5L6M7M7M8N7M6L', // 2094
|
||||||
|
'5K3I5K4K5L5L7M7N7N8N7M7L', // 2095
|
||||||
|
'5K4I4J4J4K4K6M6M6M7M6L6L', // 2096
|
||||||
|
'4J3I5K4J5K5K6M6M7M7M6L6L', // 2097
|
||||||
|
'5J3I5K4J5K5L6M7M7M8N7M6L', // 2098
|
||||||
|
'5K3I5K4K5L5L7M7N7N8N7M7L', // 2099
|
||||||
|
'5K4I5K5K5L5L7N7N7N8N7M7M', // 2100
|
||||||
|
];
|
||||||
+49
-9
@@ -2,6 +2,7 @@ import moment from 'moment-timezone';
|
|||||||
import { type unitOfTime } from 'moment/moment';
|
import { type unitOfTime } from 'moment/moment';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
type ChineseCalendarLocaleData,
|
||||||
CalendarType
|
CalendarType
|
||||||
} from '@/core/calendar.ts';
|
} from '@/core/calendar.ts';
|
||||||
import {
|
import {
|
||||||
@@ -49,6 +50,11 @@ import {
|
|||||||
ofObject
|
ofObject
|
||||||
} from './common.ts';
|
} from './common.ts';
|
||||||
|
|
||||||
|
import {
|
||||||
|
type ChineseYearMonthDayInfo,
|
||||||
|
getChineseYearMonthDayInfo
|
||||||
|
} from '@/lib/calendar/chinese_calendar.ts';
|
||||||
|
|
||||||
interface DateTimeFormatResult {
|
interface DateTimeFormatResult {
|
||||||
value: number | string;
|
value: number | string;
|
||||||
minNumeralLength?: number;
|
minNumeralLength?: number;
|
||||||
@@ -84,6 +90,7 @@ class MomentDateTime implements DateTime {
|
|||||||
};
|
};
|
||||||
|
|
||||||
private readonly instance: moment.Moment;
|
private readonly instance: moment.Moment;
|
||||||
|
private chineseDateInfo?: ChineseYearMonthDayInfo | undefined = undefined;
|
||||||
|
|
||||||
private constructor(instance: moment.Moment) {
|
private constructor(instance: moment.Moment) {
|
||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
@@ -96,6 +103,8 @@ class MomentDateTime implements DateTime {
|
|||||||
public getLocalizedCalendarYear(options: DateTimeFormatOptions): string {
|
public getLocalizedCalendarYear(options: DateTimeFormatOptions): string {
|
||||||
if (options && options.calendarType === CalendarType.Buddhist) {
|
if (options && options.calendarType === CalendarType.Buddhist) {
|
||||||
return (this.instance.year() + 543).toString();
|
return (this.instance.year() + 543).toString();
|
||||||
|
} else if (options && options.calendarType === CalendarType.Chinese) {
|
||||||
|
return this.getChineseDateInfo(options.chineseCalendarLocaleData)?.displayYear ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.instance.year().toString();
|
return this.instance.year().toString();
|
||||||
@@ -136,14 +145,12 @@ class MomentDateTime implements DateTime {
|
|||||||
return names[this.getGregorianCalendarMonth() - 1] || '';
|
return names[this.getGregorianCalendarMonth() - 1] || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
public getLocalizedCalendarMonth(options: DateTimeFormatOptions): string {
|
public getLocalizedCalendarMonth(options: DateTimeFormatOptions): string {
|
||||||
return (this.instance.month() + 1).toString();
|
if (options && options.calendarType === CalendarType.Chinese) {
|
||||||
}
|
return this.getChineseDateInfo(options.chineseCalendarLocaleData)?.displayMonth ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
return (this.instance.month() + 1).toString();
|
||||||
public getLocalizedCalendarMonthIndex(options: DateTimeFormatOptions): number {
|
|
||||||
return this.instance.month();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public getLocalizedCalendarMonthDisplayName(options: DateTimeFormatOptions): string {
|
public getLocalizedCalendarMonthDisplayName(options: DateTimeFormatOptions): string {
|
||||||
@@ -151,8 +158,12 @@ class MomentDateTime implements DateTime {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options && options.calendarType === CalendarType.Chinese) {
|
||||||
|
return this.getChineseDateInfo(options.chineseCalendarLocaleData)?.displayMonth ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
const names = options.localeData.months();
|
const names = options.localeData.months();
|
||||||
return names[this.getLocalizedCalendarMonthIndex(options)] || '';
|
return names[this.instance.month()] || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public getLocalizedCalendarMonthDisplayShortName(options: DateTimeFormatOptions): string {
|
public getLocalizedCalendarMonthDisplayShortName(options: DateTimeFormatOptions): string {
|
||||||
@@ -160,16 +171,23 @@ class MomentDateTime implements DateTime {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options && options.calendarType === CalendarType.Chinese) {
|
||||||
|
return this.getChineseDateInfo(options.chineseCalendarLocaleData)?.displayMonth ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
const names = options.localeData.monthsShort();
|
const names = options.localeData.monthsShort();
|
||||||
return names[this.getLocalizedCalendarMonthIndex(options)] || '';
|
return names[this.instance.month()] || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public getGregorianCalendarDay(): number {
|
public getGregorianCalendarDay(): number {
|
||||||
return this.instance.date();
|
return this.instance.date();
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
public getLocalizedCalendarDay(options: DateTimeFormatOptions): string {
|
public getLocalizedCalendarDay(options: DateTimeFormatOptions): string {
|
||||||
|
if (options && options.calendarType === CalendarType.Chinese) {
|
||||||
|
return this.getChineseDateInfo(options.chineseCalendarLocaleData)?.displayDay ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
return this.instance.date().toString();
|
return this.instance.date().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -307,6 +325,18 @@ class MomentDateTime implements DateTime {
|
|||||||
return new MomentDateTime(moment());
|
return new MomentDateTime(moment());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getChineseDateInfo(localeData: ChineseCalendarLocaleData): ChineseYearMonthDayInfo | undefined {
|
||||||
|
if (!this.chineseDateInfo) {
|
||||||
|
this.chineseDateInfo = getChineseYearMonthDayInfo({
|
||||||
|
year: this.instance.year(),
|
||||||
|
month: this.instance.month() + 1,
|
||||||
|
day: this.instance.date()
|
||||||
|
}, localeData);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.chineseDateInfo;
|
||||||
|
}
|
||||||
|
|
||||||
static isYearFirstTime(dateTime: MomentDateTime): boolean {
|
static isYearFirstTime(dateTime: MomentDateTime): boolean {
|
||||||
const currentUnixTime = dateTime.instance.clone().set({ millisecond: 0 }).unix();
|
const currentUnixTime = dateTime.instance.clone().set({ millisecond: 0 }).unix();
|
||||||
const expectedUnxTime = dateTime.instance.clone().set({ millisecond: 0 }).startOf('year').unix();
|
const expectedUnxTime = dateTime.instance.clone().set({ millisecond: 0 }).startOf('year').unix();
|
||||||
@@ -560,6 +590,10 @@ export function getGregorianCalendarYearAndMonthFromUnixTime(unixTime: number):
|
|||||||
return parseDateTimeFromUnixTime(unixTime).getGregorianCalendarYearDashMonth();
|
return parseDateTimeFromUnixTime(unixTime).getGregorianCalendarYearDashMonth();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getGregorianCalendarYearMonthDays(yearMonth: Year1BasedMonth): number {
|
||||||
|
return moment().set({ year: yearMonth.year, month: yearMonth.month1base - 1 }).daysInMonth();
|
||||||
|
}
|
||||||
|
|
||||||
export function getAMOrPM(hour: number): string {
|
export function getAMOrPM(hour: number): string {
|
||||||
return isPM(hour) ? MeridiemIndicator.PM.name : MeridiemIndicator.AM.name;
|
return isPM(hour) ? MeridiemIndicator.PM.name : MeridiemIndicator.AM.name;
|
||||||
}
|
}
|
||||||
@@ -572,6 +606,12 @@ export function getUnixTimeAfterUnixTime(unixTime: number, amount: number, unit:
|
|||||||
return moment.unix(unixTime).add(amount, unit).unix();
|
return moment.unix(unixTime).add(amount, unit).unix();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getDayDifference(yearMonthDay1: YearMonthDay, yearMonthDay2: YearMonthDay): number {
|
||||||
|
const date1 = moment().set({ year: yearMonthDay1.year, month: yearMonthDay1.month - 1, date: yearMonthDay1.day, hour: 0, minute: 0, second: 0, millisecond: 0 });
|
||||||
|
const date2 = moment().set({ year: yearMonthDay2.year, month: yearMonthDay2.month - 1, date: yearMonthDay2.day, hour: 0, minute: 0, second: 0, millisecond: 0 });
|
||||||
|
return date2.diff(date1, 'days');
|
||||||
|
}
|
||||||
|
|
||||||
export function getTimeDifferenceHoursAndMinutes(timeDifferenceInMinutes: number): TimeDifference {
|
export function getTimeDifferenceHoursAndMinutes(timeDifferenceInMinutes: number): TimeDifference {
|
||||||
const offsetHours = Math.trunc(Math.abs(timeDifferenceInMinutes) / 60);
|
const offsetHours = Math.trunc(Math.abs(timeDifferenceInMinutes) / 60);
|
||||||
const offsetMinutes = Math.abs(timeDifferenceInMinutes) - offsetHours * 60;
|
const offsetMinutes = Math.abs(timeDifferenceInMinutes) - offsetHours * 60;
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import zhHans from './zh_Hans.json';
|
||||||
|
import zhHant from './zh_Hant.json';
|
||||||
|
|
||||||
|
type ChineseCalendarLocaleDataKey = 'numerals' | 'monthNames' | 'dayNames' | 'leapMonthPrefix' | 'solarTermNames';
|
||||||
|
type ChineseCalendarLocaleData = {
|
||||||
|
[K in ChineseCalendarLocaleDataKey]: K extends 'leapMonthPrefix' ? string : string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DEFAULT_CONTENT: ChineseCalendarLocaleData = zhHans;
|
||||||
|
|
||||||
|
export const ALL_LANGUAGES: Record<string, ChineseCalendarLocaleData> = {
|
||||||
|
'zh-Hans': zhHans,
|
||||||
|
'zh-Hant': zhHant
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
{
|
||||||
|
"numerals": [
|
||||||
|
"〇",
|
||||||
|
"一",
|
||||||
|
"二",
|
||||||
|
"三",
|
||||||
|
"四",
|
||||||
|
"五",
|
||||||
|
"六",
|
||||||
|
"七",
|
||||||
|
"八",
|
||||||
|
"九",
|
||||||
|
"十"
|
||||||
|
],
|
||||||
|
"monthNames": [
|
||||||
|
"正月",
|
||||||
|
"二月",
|
||||||
|
"三月",
|
||||||
|
"四月",
|
||||||
|
"五月",
|
||||||
|
"六月",
|
||||||
|
"七月",
|
||||||
|
"八月",
|
||||||
|
"九月",
|
||||||
|
"十月",
|
||||||
|
"冬月",
|
||||||
|
"腊月"
|
||||||
|
],
|
||||||
|
"dayNames": [
|
||||||
|
"初一",
|
||||||
|
"初二",
|
||||||
|
"初三",
|
||||||
|
"初四",
|
||||||
|
"初五",
|
||||||
|
"初六",
|
||||||
|
"初七",
|
||||||
|
"初八",
|
||||||
|
"初九",
|
||||||
|
"初十",
|
||||||
|
"十一",
|
||||||
|
"十二",
|
||||||
|
"十三",
|
||||||
|
"十四",
|
||||||
|
"十五",
|
||||||
|
"十六",
|
||||||
|
"十七",
|
||||||
|
"十八",
|
||||||
|
"十九",
|
||||||
|
"二十",
|
||||||
|
"廿一",
|
||||||
|
"廿二",
|
||||||
|
"廿三",
|
||||||
|
"廿四",
|
||||||
|
"廿五",
|
||||||
|
"廿六",
|
||||||
|
"廿七",
|
||||||
|
"廿八",
|
||||||
|
"廿九",
|
||||||
|
"三十"
|
||||||
|
],
|
||||||
|
"leapMonthPrefix": "闰",
|
||||||
|
"solarTermNames": [
|
||||||
|
"小寒",
|
||||||
|
"大寒",
|
||||||
|
"立春",
|
||||||
|
"雨水",
|
||||||
|
"惊蛰",
|
||||||
|
"春分",
|
||||||
|
"清明",
|
||||||
|
"谷雨",
|
||||||
|
"立夏",
|
||||||
|
"小满",
|
||||||
|
"芒种",
|
||||||
|
"夏至",
|
||||||
|
"小暑",
|
||||||
|
"大暑",
|
||||||
|
"立秋",
|
||||||
|
"处暑",
|
||||||
|
"白露",
|
||||||
|
"秋分",
|
||||||
|
"寒露",
|
||||||
|
"霜降",
|
||||||
|
"立冬",
|
||||||
|
"小雪",
|
||||||
|
"大雪",
|
||||||
|
"冬至"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
{
|
||||||
|
"numerals": [
|
||||||
|
"〇",
|
||||||
|
"一",
|
||||||
|
"二",
|
||||||
|
"三",
|
||||||
|
"四",
|
||||||
|
"五",
|
||||||
|
"六",
|
||||||
|
"七",
|
||||||
|
"八",
|
||||||
|
"九",
|
||||||
|
"十"
|
||||||
|
],
|
||||||
|
"monthNames": [
|
||||||
|
"正月",
|
||||||
|
"二月",
|
||||||
|
"三月",
|
||||||
|
"四月",
|
||||||
|
"五月",
|
||||||
|
"六月",
|
||||||
|
"七月",
|
||||||
|
"八月",
|
||||||
|
"九月",
|
||||||
|
"十月",
|
||||||
|
"冬月",
|
||||||
|
"腊月"
|
||||||
|
],
|
||||||
|
"dayNames": [
|
||||||
|
"初一",
|
||||||
|
"初二",
|
||||||
|
"初三",
|
||||||
|
"初四",
|
||||||
|
"初五",
|
||||||
|
"初六",
|
||||||
|
"初七",
|
||||||
|
"初八",
|
||||||
|
"初九",
|
||||||
|
"初十",
|
||||||
|
"十一",
|
||||||
|
"十二",
|
||||||
|
"十三",
|
||||||
|
"十四",
|
||||||
|
"十五",
|
||||||
|
"十六",
|
||||||
|
"十七",
|
||||||
|
"十八",
|
||||||
|
"十九",
|
||||||
|
"二十",
|
||||||
|
"廿一",
|
||||||
|
"廿二",
|
||||||
|
"廿三",
|
||||||
|
"廿四",
|
||||||
|
"廿五",
|
||||||
|
"廿六",
|
||||||
|
"廿七",
|
||||||
|
"廿八",
|
||||||
|
"廿九",
|
||||||
|
"三十"
|
||||||
|
],
|
||||||
|
"leapMonthPrefix": "閏",
|
||||||
|
"solarTermNames": [
|
||||||
|
"小寒",
|
||||||
|
"大寒",
|
||||||
|
"立春",
|
||||||
|
"雨水",
|
||||||
|
"驚蟄",
|
||||||
|
"春分",
|
||||||
|
"清明",
|
||||||
|
"穀雨",
|
||||||
|
"立夏",
|
||||||
|
"小滿",
|
||||||
|
"芒種",
|
||||||
|
"夏至",
|
||||||
|
"小暑",
|
||||||
|
"大暑",
|
||||||
|
"立秋",
|
||||||
|
"處暑",
|
||||||
|
"白露",
|
||||||
|
"秋分",
|
||||||
|
"寒露",
|
||||||
|
"霜降",
|
||||||
|
"立冬",
|
||||||
|
"小雪",
|
||||||
|
"大雪",
|
||||||
|
"冬至"
|
||||||
|
]
|
||||||
|
}
|
||||||
+2
-1
@@ -138,7 +138,8 @@
|
|||||||
},
|
},
|
||||||
"calendar": {
|
"calendar": {
|
||||||
"Gregorian": "Gregorian",
|
"Gregorian": "Gregorian",
|
||||||
"Buddhist": "Buddhist"
|
"Buddhist": "Buddhist",
|
||||||
|
"Gregorian with Chinese": "Gregorian with Chinese"
|
||||||
},
|
},
|
||||||
"datetime": {
|
"datetime": {
|
||||||
"AM": {
|
"AM": {
|
||||||
|
|||||||
+2
-1
@@ -138,7 +138,8 @@
|
|||||||
},
|
},
|
||||||
"calendar": {
|
"calendar": {
|
||||||
"Gregorian": "Gregorian",
|
"Gregorian": "Gregorian",
|
||||||
"Buddhist": "Buddhist"
|
"Buddhist": "Buddhist",
|
||||||
|
"Gregorian with Chinese": "Gregorian with Chinese"
|
||||||
},
|
},
|
||||||
"datetime": {
|
"datetime": {
|
||||||
"AM": {
|
"AM": {
|
||||||
|
|||||||
+2
-1
@@ -138,7 +138,8 @@
|
|||||||
},
|
},
|
||||||
"calendar": {
|
"calendar": {
|
||||||
"Gregorian": "Gregorian",
|
"Gregorian": "Gregorian",
|
||||||
"Buddhist": "Buddhist"
|
"Buddhist": "Buddhist",
|
||||||
|
"Gregorian with Chinese": "Gregorian with Chinese"
|
||||||
},
|
},
|
||||||
"datetime": {
|
"datetime": {
|
||||||
"AM": {
|
"AM": {
|
||||||
|
|||||||
+83
-1
@@ -11,11 +11,17 @@ import {
|
|||||||
DEFAULT_LANGUAGE
|
DEFAULT_LANGUAGE
|
||||||
} from '@/locales/index.ts';
|
} from '@/locales/index.ts';
|
||||||
|
|
||||||
|
import {
|
||||||
|
ALL_LANGUAGES as CHINESE_CALENDAR_ALL_LANGUAGES,
|
||||||
|
DEFAULT_CONTENT as CHINESE_CALENDAR_DEFAULT_CONTENT
|
||||||
|
} from '@/locales/calendar/chinese/index.ts';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
TextDirection
|
TextDirection
|
||||||
} from '@/core/text.ts';
|
} from '@/core/text.ts';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
type ChineseCalendarLocaleData,
|
||||||
CalendarType,
|
CalendarType,
|
||||||
CalendarDisplayType,
|
CalendarDisplayType,
|
||||||
DateDisplayType
|
DateDisplayType
|
||||||
@@ -26,6 +32,9 @@ import {
|
|||||||
type DateTimeLocaleData,
|
type DateTimeLocaleData,
|
||||||
type TextualYearMonth,
|
type TextualYearMonth,
|
||||||
type TextualYearMonthDay,
|
type TextualYearMonthDay,
|
||||||
|
type Year1BasedMonth,
|
||||||
|
type YearMonthDay,
|
||||||
|
type CalendarAlternateDate,
|
||||||
type DateFormat,
|
type DateFormat,
|
||||||
type TimeFormat,
|
type TimeFormat,
|
||||||
type LocalizedDateTimeFormat,
|
type LocalizedDateTimeFormat,
|
||||||
@@ -178,6 +187,13 @@ import {
|
|||||||
isPM
|
isPM
|
||||||
} from '@/lib/datetime.ts';
|
} from '@/lib/datetime.ts';
|
||||||
|
|
||||||
|
import {
|
||||||
|
type ChineseYearMonthDayInfo,
|
||||||
|
getChineseYearMonthAllDayInfos,
|
||||||
|
getChineseYearMonthDayInfo,
|
||||||
|
getChineseCalendarAlternateDisplayDate
|
||||||
|
} from '@/lib/calendar/chinese_calendar.ts';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
appendDigitGroupingSymbolAndDecimalSeparator,
|
appendDigitGroupingSymbolAndDecimalSeparator,
|
||||||
parseAmount,
|
parseAmount,
|
||||||
@@ -452,6 +468,19 @@ export function useI18n() {
|
|||||||
return moment.localeData();
|
return moment.localeData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getChineseCalendarLocaleData(): ChineseCalendarLocaleData {
|
||||||
|
const localeData = CHINESE_CALENDAR_ALL_LANGUAGES[locale.value] ?? CHINESE_CALENDAR_DEFAULT_CONTENT;
|
||||||
|
const chineseCalendarLocaleData: ChineseCalendarLocaleData = {
|
||||||
|
numerals: localeData['numerals'],
|
||||||
|
monthNames: localeData['monthNames'],
|
||||||
|
dayNames: localeData['dayNames'],
|
||||||
|
leapMonthPrefix: localeData['leapMonthPrefix'],
|
||||||
|
solarTermNames: localeData['solarTermNames']
|
||||||
|
};
|
||||||
|
|
||||||
|
return chineseCalendarLocaleData;
|
||||||
|
}
|
||||||
|
|
||||||
function getAllCurrencyDisplayTypes(numeralSystem: NumeralSystem, decimalSeparator: string): TypeAndDisplayName[] {
|
function getAllCurrencyDisplayTypes(numeralSystem: NumeralSystem, decimalSeparator: string): TypeAndDisplayName[] {
|
||||||
const defaultCurrencyDisplayTypeName = t('default.currencyDisplayType');
|
const defaultCurrencyDisplayTypeName = t('default.currencyDisplayType');
|
||||||
let defaultCurrencyDisplayType = CurrencyDisplayType.parse(defaultCurrencyDisplayTypeName);
|
let defaultCurrencyDisplayType = CurrencyDisplayType.parse(defaultCurrencyDisplayTypeName);
|
||||||
@@ -683,7 +712,8 @@ export function useI18n() {
|
|||||||
return {
|
return {
|
||||||
numeralSystem: numeralSystem,
|
numeralSystem: numeralSystem,
|
||||||
calendarType: calendarType,
|
calendarType: calendarType,
|
||||||
localeData: getDateTimeLocaleData()
|
localeData: getDateTimeLocaleData(),
|
||||||
|
chineseCalendarLocaleData: getChineseCalendarLocaleData()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1869,6 +1899,56 @@ export function useI18n() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getCalendarAlternateDates(yearMonth: Year1BasedMonth): CalendarAlternateDate[] | undefined {
|
||||||
|
const calendarDisplayType = getCurrentCalendarDisplayType().secondaryCalendarType;
|
||||||
|
|
||||||
|
if (!calendarDisplayType) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (calendarDisplayType === CalendarType.Chinese) {
|
||||||
|
const chineseCalendarLocaleData = getChineseCalendarLocaleData();
|
||||||
|
const chineseDates: ChineseYearMonthDayInfo[] | undefined = getChineseYearMonthAllDayInfos(yearMonth, chineseCalendarLocaleData);
|
||||||
|
|
||||||
|
if (!chineseDates) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ret: CalendarAlternateDate[] = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < chineseDates.length; i++) {
|
||||||
|
const chineseDate = chineseDates[i];
|
||||||
|
const alternateDate = getChineseCalendarAlternateDisplayDate(chineseDate);
|
||||||
|
ret.push(alternateDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCalendarAlternateDate(yearMonthDay: YearMonthDay): CalendarAlternateDate | undefined {
|
||||||
|
const calendarDisplayType = getCurrentCalendarDisplayType().secondaryCalendarType;
|
||||||
|
|
||||||
|
if (!calendarDisplayType) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (calendarDisplayType === CalendarType.Chinese) {
|
||||||
|
const chineseCalendarLocaleData = getChineseCalendarLocaleData();
|
||||||
|
const chineseDate: ChineseYearMonthDayInfo | undefined = getChineseYearMonthDayInfo(yearMonthDay, chineseCalendarLocaleData);
|
||||||
|
|
||||||
|
if (!chineseDate) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return getChineseCalendarAlternateDisplayDate(chineseDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
function getParsedAmountNumber(value: string, numeralSystem?: NumeralSystem): number {
|
function getParsedAmountNumber(value: string, numeralSystem?: NumeralSystem): number {
|
||||||
const numberFormatOptions = getNumberFormatOptions({ numeralSystem });
|
const numberFormatOptions = getNumberFormatOptions({ numeralSystem });
|
||||||
return parseAmount(value, numberFormatOptions);
|
return parseAmount(value, numberFormatOptions);
|
||||||
@@ -2288,6 +2368,8 @@ export function useI18n() {
|
|||||||
formatUnixTimeToFiscalYear,
|
formatUnixTimeToFiscalYear,
|
||||||
formatYearToFiscalYear,
|
formatYearToFiscalYear,
|
||||||
getTimezoneDifferenceDisplayText,
|
getTimezoneDifferenceDisplayText,
|
||||||
|
getCalendarAlternateDates,
|
||||||
|
getCalendarAlternateDate,
|
||||||
parseAmountFromLocalizedNumerals: (value: string) => getParsedAmountNumber(value),
|
parseAmountFromLocalizedNumerals: (value: string) => getParsedAmountNumber(value),
|
||||||
parseAmountFromWesternArabicNumerals: (value: string) => getParsedAmountNumber(value, NumeralSystem.WesternArabicNumerals),
|
parseAmountFromWesternArabicNumerals: (value: string) => getParsedAmountNumber(value, NumeralSystem.WesternArabicNumerals),
|
||||||
formatAmountToLocalizedNumerals: (value: number, currencyCode?: string) => getFormattedAmount(value, undefined, undefined, currencyCode),
|
formatAmountToLocalizedNumerals: (value: number, currencyCode?: string) => getFormattedAmount(value, undefined, undefined, currencyCode),
|
||||||
|
|||||||
+2
-1
@@ -138,7 +138,8 @@
|
|||||||
},
|
},
|
||||||
"calendar": {
|
"calendar": {
|
||||||
"Gregorian": "Gregorian",
|
"Gregorian": "Gregorian",
|
||||||
"Buddhist": "Buddhist"
|
"Buddhist": "Buddhist",
|
||||||
|
"Gregorian with Chinese": "Gregorian with Chinese"
|
||||||
},
|
},
|
||||||
"datetime": {
|
"datetime": {
|
||||||
"AM": {
|
"AM": {
|
||||||
|
|||||||
+2
-1
@@ -138,7 +138,8 @@
|
|||||||
},
|
},
|
||||||
"calendar": {
|
"calendar": {
|
||||||
"Gregorian": "Gregorian",
|
"Gregorian": "Gregorian",
|
||||||
"Buddhist": "Buddhist"
|
"Buddhist": "Buddhist",
|
||||||
|
"Gregorian with Chinese": "Gregorian with Chinese"
|
||||||
},
|
},
|
||||||
"datetime": {
|
"datetime": {
|
||||||
"AM": {
|
"AM": {
|
||||||
|
|||||||
+2
-1
@@ -138,7 +138,8 @@
|
|||||||
},
|
},
|
||||||
"calendar": {
|
"calendar": {
|
||||||
"Gregorian": "Gregorian",
|
"Gregorian": "Gregorian",
|
||||||
"Buddhist": "Buddhist"
|
"Buddhist": "Buddhist",
|
||||||
|
"Gregorian with Chinese": "Gregorian with Chinese"
|
||||||
},
|
},
|
||||||
"datetime": {
|
"datetime": {
|
||||||
"AM": {
|
"AM": {
|
||||||
|
|||||||
@@ -138,7 +138,8 @@
|
|||||||
},
|
},
|
||||||
"calendar": {
|
"calendar": {
|
||||||
"Gregorian": "Gregorian",
|
"Gregorian": "Gregorian",
|
||||||
"Buddhist": "Buddhist"
|
"Buddhist": "Buddhist",
|
||||||
|
"Gregorian with Chinese": "Gregorian with Chinese"
|
||||||
},
|
},
|
||||||
"datetime": {
|
"datetime": {
|
||||||
"AM": {
|
"AM": {
|
||||||
|
|||||||
+2
-1
@@ -138,7 +138,8 @@
|
|||||||
},
|
},
|
||||||
"calendar": {
|
"calendar": {
|
||||||
"Gregorian": "Gregorian",
|
"Gregorian": "Gregorian",
|
||||||
"Buddhist": "Buddhist"
|
"Buddhist": "Buddhist",
|
||||||
|
"Gregorian with Chinese": "Gregorian with Chinese"
|
||||||
},
|
},
|
||||||
"datetime": {
|
"datetime": {
|
||||||
"AM": {
|
"AM": {
|
||||||
|
|||||||
+2
-1
@@ -138,7 +138,8 @@
|
|||||||
},
|
},
|
||||||
"calendar": {
|
"calendar": {
|
||||||
"Gregorian": "Gregorian",
|
"Gregorian": "Gregorian",
|
||||||
"Buddhist": "Buddhist"
|
"Buddhist": "Buddhist",
|
||||||
|
"Gregorian with Chinese": "Gregorian with Chinese"
|
||||||
},
|
},
|
||||||
"datetime": {
|
"datetime": {
|
||||||
"AM": {
|
"AM": {
|
||||||
|
|||||||
+2
-1
@@ -138,7 +138,8 @@
|
|||||||
},
|
},
|
||||||
"calendar": {
|
"calendar": {
|
||||||
"Gregorian": "Gregorian",
|
"Gregorian": "Gregorian",
|
||||||
"Buddhist": "Buddhist"
|
"Buddhist": "Buddhist",
|
||||||
|
"Gregorian with Chinese": "Gregorian with Chinese"
|
||||||
},
|
},
|
||||||
"datetime": {
|
"datetime": {
|
||||||
"AM": {
|
"AM": {
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
"currency": "CNY",
|
"currency": "CNY",
|
||||||
"firstDayOfWeek": "Monday",
|
"firstDayOfWeek": "Monday",
|
||||||
"fiscalYearFormat": "EndYYYY",
|
"fiscalYearFormat": "EndYYYY",
|
||||||
"calendarDisplayType": "Gregorian",
|
"calendarDisplayType": "GregorianWithChinese",
|
||||||
"dateDisplayType": "Gregorian",
|
"dateDisplayType": "Gregorian",
|
||||||
"longDateFormat": "YYYYMMDD",
|
"longDateFormat": "YYYYMMDD",
|
||||||
"shortDateFormat": "YYYYMMDD",
|
"shortDateFormat": "YYYYMMDD",
|
||||||
@@ -138,7 +138,8 @@
|
|||||||
},
|
},
|
||||||
"calendar": {
|
"calendar": {
|
||||||
"Gregorian": "公历",
|
"Gregorian": "公历",
|
||||||
"Buddhist": "佛教日历"
|
"Buddhist": "佛教日历",
|
||||||
|
"Gregorian with Chinese": "公历+农历"
|
||||||
},
|
},
|
||||||
"datetime": {
|
"datetime": {
|
||||||
"AM": {
|
"AM": {
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
"currency": "TWD",
|
"currency": "TWD",
|
||||||
"firstDayOfWeek": "Sunday",
|
"firstDayOfWeek": "Sunday",
|
||||||
"fiscalYearFormat": "EndYYYY",
|
"fiscalYearFormat": "EndYYYY",
|
||||||
"calendarDisplayType": "Gregorian",
|
"calendarDisplayType": "GregorianWithChinese",
|
||||||
"dateDisplayType": "Gregorian",
|
"dateDisplayType": "Gregorian",
|
||||||
"longDateFormat": "YYYYMMDD",
|
"longDateFormat": "YYYYMMDD",
|
||||||
"shortDateFormat": "YYYYMMDD",
|
"shortDateFormat": "YYYYMMDD",
|
||||||
@@ -138,7 +138,8 @@
|
|||||||
},
|
},
|
||||||
"calendar": {
|
"calendar": {
|
||||||
"Gregorian": "公曆",
|
"Gregorian": "公曆",
|
||||||
"Buddhist": "佛曆"
|
"Buddhist": "佛曆",
|
||||||
|
"Gregorian with Chinese": "公曆+農曆"
|
||||||
},
|
},
|
||||||
"datetime": {
|
"datetime": {
|
||||||
"AM": {
|
"AM": {
|
||||||
|
|||||||
+2
-3
@@ -3,7 +3,6 @@ import { defineStore } from 'pinia';
|
|||||||
|
|
||||||
import { useSettingsStore } from './setting.ts';
|
import { useSettingsStore } from './setting.ts';
|
||||||
|
|
||||||
import { CalendarDisplayType, DateDisplayType } from '@/core/calendar.ts';
|
|
||||||
import { type WeekDayValue, WeekDay } from '@/core/datetime.ts';
|
import { type WeekDayValue, WeekDay } from '@/core/datetime.ts';
|
||||||
import { FiscalYearStart } from '@/core/fiscalyear.ts';
|
import { FiscalYearStart } from '@/core/fiscalyear.ts';
|
||||||
import type { ApplicationCloudSetting } from '@/core/setting.ts';
|
import type { ApplicationCloudSetting } from '@/core/setting.ts';
|
||||||
@@ -77,12 +76,12 @@ export const useUserStore = defineStore('user', () => {
|
|||||||
|
|
||||||
const currentUserCalendarDisplayType = computed<number>(() => {
|
const currentUserCalendarDisplayType = computed<number>(() => {
|
||||||
const userInfo = currentUserBasicInfo.value || EMPTY_USER_BASIC_INFO;
|
const userInfo = currentUserBasicInfo.value || EMPTY_USER_BASIC_INFO;
|
||||||
return isNumber(userInfo.calendarDisplayType) && CalendarDisplayType.valueOf(userInfo.calendarDisplayType) ? userInfo.calendarDisplayType : EMPTY_USER_BASIC_INFO.calendarDisplayType;
|
return userInfo.calendarDisplayType;
|
||||||
});
|
});
|
||||||
|
|
||||||
const currentUserDateDisplayType = computed<number>(() => {
|
const currentUserDateDisplayType = computed<number>(() => {
|
||||||
const userInfo = currentUserBasicInfo.value || EMPTY_USER_BASIC_INFO;
|
const userInfo = currentUserBasicInfo.value || EMPTY_USER_BASIC_INFO;
|
||||||
return isNumber(userInfo.dateDisplayType) && DateDisplayType.valueOf(userInfo.dateDisplayType) ? userInfo.dateDisplayType : EMPTY_USER_BASIC_INFO.dateDisplayType;
|
return userInfo.dateDisplayType;
|
||||||
});
|
});
|
||||||
|
|
||||||
const currentUserLongDateFormat = computed<number>(() => {
|
const currentUserLongDateFormat = computed<number>(() => {
|
||||||
|
|||||||
@@ -65,6 +65,7 @@
|
|||||||
--ebk-numpad-value-large-font-size: 24px;
|
--ebk-numpad-value-large-font-size: 24px;
|
||||||
--ebk-numpad-normal-button-font-size: 28px;
|
--ebk-numpad-normal-button-font-size: 28px;
|
||||||
--ebk-numpad-confirm-button-font-size: 20px;
|
--ebk-numpad-confirm-button-font-size: 20px;
|
||||||
|
--ebk-datetime-picker-alternate-date-font-size: 12px;
|
||||||
--ebk-amount-small-font-size: 32px;
|
--ebk-amount-small-font-size: 32px;
|
||||||
--ebk-amount-normal-font-size: 36px;
|
--ebk-amount-normal-font-size: 36px;
|
||||||
--ebk-amount-large-font-size: 40px;
|
--ebk-amount-large-font-size: 40px;
|
||||||
@@ -78,8 +79,10 @@
|
|||||||
--ebk-transaction-date-width: 25px;
|
--ebk-transaction-date-width: 25px;
|
||||||
--ebk-transaction-day-font-size: 16px;
|
--ebk-transaction-day-font-size: 16px;
|
||||||
--ebk-transaction-day-of-week-font-size: 12px;
|
--ebk-transaction-day-of-week-font-size: 12px;
|
||||||
|
--ebk-transaction-calendar-alternate-date-font-size: 11px;
|
||||||
--ebk-transaction-calendar-amount-font-size: 11px;
|
--ebk-transaction-calendar-amount-font-size: 11px;
|
||||||
--ebk-transaction-calendar-daily-amounts-height: 65px;
|
--ebk-transaction-calendar-daily-amounts-height: 65px;
|
||||||
|
--ebk-transaction-calendar-with-alternate-date-daily-amounts-height: 75px;
|
||||||
--ebk-transaction-account-arrow-font-size: 12px;
|
--ebk-transaction-account-arrow-font-size: 12px;
|
||||||
--ebk-transaction-account-arrow-margin-top: -1px;
|
--ebk-transaction-account-arrow-margin-top: -1px;
|
||||||
--ebk-transaction-tag-icon-font-size: 22px;
|
--ebk-transaction-tag-icon-font-size: 22px;
|
||||||
|
|||||||
@@ -65,6 +65,7 @@
|
|||||||
--ebk-numpad-value-large-font-size: 25px;
|
--ebk-numpad-value-large-font-size: 25px;
|
||||||
--ebk-numpad-normal-button-font-size: 29px;
|
--ebk-numpad-normal-button-font-size: 29px;
|
||||||
--ebk-numpad-confirm-button-font-size: 21px;
|
--ebk-numpad-confirm-button-font-size: 21px;
|
||||||
|
--ebk-datetime-picker-alternate-date-font-size: 13px;
|
||||||
--ebk-amount-small-font-size: 32px;
|
--ebk-amount-small-font-size: 32px;
|
||||||
--ebk-amount-normal-font-size: 36px;
|
--ebk-amount-normal-font-size: 36px;
|
||||||
--ebk-amount-large-font-size: 40px;
|
--ebk-amount-large-font-size: 40px;
|
||||||
@@ -78,8 +79,10 @@
|
|||||||
--ebk-transaction-date-width: 28px;
|
--ebk-transaction-date-width: 28px;
|
||||||
--ebk-transaction-day-font-size: 17px;
|
--ebk-transaction-day-font-size: 17px;
|
||||||
--ebk-transaction-day-of-week-font-size: 13px;
|
--ebk-transaction-day-of-week-font-size: 13px;
|
||||||
|
--ebk-transaction-calendar-alternate-date-font-size: 13px;
|
||||||
--ebk-transaction-calendar-amount-font-size: 13px;
|
--ebk-transaction-calendar-amount-font-size: 13px;
|
||||||
--ebk-transaction-calendar-daily-amounts-height: 65px;
|
--ebk-transaction-calendar-daily-amounts-height: 65px;
|
||||||
|
--ebk-transaction-calendar-with-alternate-date-daily-amounts-height: 80px;
|
||||||
--ebk-transaction-account-arrow-font-size: 13px;
|
--ebk-transaction-account-arrow-font-size: 13px;
|
||||||
--ebk-transaction-account-arrow-margin-top: -2px;
|
--ebk-transaction-account-arrow-margin-top: -2px;
|
||||||
--ebk-transaction-tag-icon-font-size: 24px;
|
--ebk-transaction-tag-icon-font-size: 24px;
|
||||||
|
|||||||
@@ -65,6 +65,7 @@
|
|||||||
--ebk-numpad-value-large-font-size: 24px;
|
--ebk-numpad-value-large-font-size: 24px;
|
||||||
--ebk-numpad-normal-button-font-size: 28px;
|
--ebk-numpad-normal-button-font-size: 28px;
|
||||||
--ebk-numpad-confirm-button-font-size: 20px;
|
--ebk-numpad-confirm-button-font-size: 20px;
|
||||||
|
--ebk-datetime-picker-alternate-date-font-size: 11px;
|
||||||
--ebk-amount-small-font-size: 32px;
|
--ebk-amount-small-font-size: 32px;
|
||||||
--ebk-amount-normal-font-size: 36px;
|
--ebk-amount-normal-font-size: 36px;
|
||||||
--ebk-amount-large-font-size: 40px;
|
--ebk-amount-large-font-size: 40px;
|
||||||
@@ -78,8 +79,10 @@
|
|||||||
--ebk-transaction-date-width: 25px;
|
--ebk-transaction-date-width: 25px;
|
||||||
--ebk-transaction-day-font-size: 16px;
|
--ebk-transaction-day-font-size: 16px;
|
||||||
--ebk-transaction-day-of-week-font-size: 12px;
|
--ebk-transaction-day-of-week-font-size: 12px;
|
||||||
|
--ebk-transaction-calendar-alternate-date-font-size: 10px;
|
||||||
--ebk-transaction-calendar-amount-font-size: 10px;
|
--ebk-transaction-calendar-amount-font-size: 10px;
|
||||||
--ebk-transaction-calendar-daily-amounts-height: 60px;
|
--ebk-transaction-calendar-daily-amounts-height: 60px;
|
||||||
|
--ebk-transaction-calendar-with-alternate-date-daily-amounts-height: 70px;
|
||||||
--ebk-transaction-account-arrow-font-size: 12px;
|
--ebk-transaction-account-arrow-font-size: 12px;
|
||||||
--ebk-transaction-account-arrow-margin-top: -1px;
|
--ebk-transaction-account-arrow-margin-top: -1px;
|
||||||
--ebk-transaction-tag-icon-font-size: 20px;
|
--ebk-transaction-tag-icon-font-size: 20px;
|
||||||
|
|||||||
@@ -65,6 +65,7 @@
|
|||||||
--ebk-numpad-value-large-font-size: 26px;
|
--ebk-numpad-value-large-font-size: 26px;
|
||||||
--ebk-numpad-normal-button-font-size: 30px;
|
--ebk-numpad-normal-button-font-size: 30px;
|
||||||
--ebk-numpad-confirm-button-font-size: 22px;
|
--ebk-numpad-confirm-button-font-size: 22px;
|
||||||
|
--ebk-datetime-picker-alternate-date-font-size: 14px;
|
||||||
--ebk-amount-small-font-size: 32px;
|
--ebk-amount-small-font-size: 32px;
|
||||||
--ebk-amount-normal-font-size: 36px;
|
--ebk-amount-normal-font-size: 36px;
|
||||||
--ebk-amount-large-font-size: 40px;
|
--ebk-amount-large-font-size: 40px;
|
||||||
@@ -78,8 +79,10 @@
|
|||||||
--ebk-transaction-date-width: 30px;
|
--ebk-transaction-date-width: 30px;
|
||||||
--ebk-transaction-day-font-size: 18px;
|
--ebk-transaction-day-font-size: 18px;
|
||||||
--ebk-transaction-day-of-week-font-size: 14px;
|
--ebk-transaction-day-of-week-font-size: 14px;
|
||||||
|
--ebk-transaction-calendar-alternate-date-font-size: 14px;
|
||||||
--ebk-transaction-calendar-amount-font-size: 14px;
|
--ebk-transaction-calendar-amount-font-size: 14px;
|
||||||
--ebk-transaction-calendar-daily-amounts-height: 70px;
|
--ebk-transaction-calendar-daily-amounts-height: 70px;
|
||||||
|
--ebk-transaction-calendar-with-alternate-date-daily-amounts-height: 90px;
|
||||||
--ebk-transaction-account-arrow-font-size: 14px;
|
--ebk-transaction-account-arrow-font-size: 14px;
|
||||||
--ebk-transaction-account-arrow-margin-top: -2px;
|
--ebk-transaction-account-arrow-margin-top: -2px;
|
||||||
--ebk-transaction-tag-icon-font-size: 26px;
|
--ebk-transaction-tag-icon-font-size: 26px;
|
||||||
|
|||||||
@@ -65,6 +65,7 @@
|
|||||||
--ebk-numpad-value-large-font-size: 30px;
|
--ebk-numpad-value-large-font-size: 30px;
|
||||||
--ebk-numpad-normal-button-font-size: 32px;
|
--ebk-numpad-normal-button-font-size: 32px;
|
||||||
--ebk-numpad-confirm-button-font-size: 22px;
|
--ebk-numpad-confirm-button-font-size: 22px;
|
||||||
|
--ebk-datetime-picker-alternate-date-font-size: 15px;
|
||||||
--ebk-amount-small-font-size: 32px;
|
--ebk-amount-small-font-size: 32px;
|
||||||
--ebk-amount-normal-font-size: 36px;
|
--ebk-amount-normal-font-size: 36px;
|
||||||
--ebk-amount-large-font-size: 40px;
|
--ebk-amount-large-font-size: 40px;
|
||||||
@@ -78,8 +79,10 @@
|
|||||||
--ebk-transaction-date-width: 32px;
|
--ebk-transaction-date-width: 32px;
|
||||||
--ebk-transaction-day-font-size: 20px;
|
--ebk-transaction-day-font-size: 20px;
|
||||||
--ebk-transaction-day-of-week-font-size: 15px;
|
--ebk-transaction-day-of-week-font-size: 15px;
|
||||||
|
--ebk-transaction-calendar-alternate-date-font-size: 15px;
|
||||||
--ebk-transaction-calendar-amount-font-size: 15px;
|
--ebk-transaction-calendar-amount-font-size: 15px;
|
||||||
--ebk-transaction-calendar-daily-amounts-height: 75px;
|
--ebk-transaction-calendar-daily-amounts-height: 75px;
|
||||||
|
--ebk-transaction-calendar-with-alternate-date-daily-amounts-height: 100px;
|
||||||
--ebk-transaction-account-arrow-font-size: 15px;
|
--ebk-transaction-account-arrow-font-size: 15px;
|
||||||
--ebk-transaction-account-arrow-margin-top: -3px;
|
--ebk-transaction-account-arrow-margin-top: -3px;
|
||||||
--ebk-transaction-tag-icon-font-size: 28px;
|
--ebk-transaction-tag-icon-font-size: 28px;
|
||||||
|
|||||||
@@ -65,6 +65,7 @@
|
|||||||
--ebk-numpad-value-large-font-size: 30px;
|
--ebk-numpad-value-large-font-size: 30px;
|
||||||
--ebk-numpad-normal-button-font-size: 32px;
|
--ebk-numpad-normal-button-font-size: 32px;
|
||||||
--ebk-numpad-confirm-button-font-size: 24px;
|
--ebk-numpad-confirm-button-font-size: 24px;
|
||||||
|
--ebk-datetime-picker-alternate-date-font-size: 17px;
|
||||||
--ebk-amount-small-font-size: 34px;
|
--ebk-amount-small-font-size: 34px;
|
||||||
--ebk-amount-normal-font-size: 38px;
|
--ebk-amount-normal-font-size: 38px;
|
||||||
--ebk-amount-large-font-size: 42px;
|
--ebk-amount-large-font-size: 42px;
|
||||||
@@ -78,8 +79,10 @@
|
|||||||
--ebk-transaction-date-width: 36px;
|
--ebk-transaction-date-width: 36px;
|
||||||
--ebk-transaction-day-font-size: 22px;
|
--ebk-transaction-day-font-size: 22px;
|
||||||
--ebk-transaction-day-of-week-font-size: 17px;
|
--ebk-transaction-day-of-week-font-size: 17px;
|
||||||
|
--ebk-transaction-calendar-alternate-date-font-size: 17px;
|
||||||
--ebk-transaction-calendar-amount-font-size: 17px;
|
--ebk-transaction-calendar-amount-font-size: 17px;
|
||||||
--ebk-transaction-calendar-daily-amounts-height: 80px;
|
--ebk-transaction-calendar-daily-amounts-height: 80px;
|
||||||
|
--ebk-transaction-calendar-with-alternate-date-daily-amounts-height: 105px;
|
||||||
--ebk-transaction-account-arrow-font-size: 17px;
|
--ebk-transaction-account-arrow-font-size: 17px;
|
||||||
--ebk-transaction-account-arrow-margin-top: -4px;
|
--ebk-transaction-account-arrow-margin-top: -4px;
|
||||||
--ebk-transaction-tag-icon-font-size: 30px;
|
--ebk-transaction-tag-icon-font-size: 30px;
|
||||||
|
|||||||
@@ -65,6 +65,7 @@
|
|||||||
--ebk-numpad-value-large-font-size: 30px;
|
--ebk-numpad-value-large-font-size: 30px;
|
||||||
--ebk-numpad-normal-button-font-size: 32px;
|
--ebk-numpad-normal-button-font-size: 32px;
|
||||||
--ebk-numpad-confirm-button-font-size: 26px;
|
--ebk-numpad-confirm-button-font-size: 26px;
|
||||||
|
--ebk-datetime-picker-alternate-date-font-size: 19px;
|
||||||
--ebk-amount-small-font-size: 34px;
|
--ebk-amount-small-font-size: 34px;
|
||||||
--ebk-amount-normal-font-size: 40px;
|
--ebk-amount-normal-font-size: 40px;
|
||||||
--ebk-amount-large-font-size: 44px;
|
--ebk-amount-large-font-size: 44px;
|
||||||
@@ -78,8 +79,10 @@
|
|||||||
--ebk-transaction-date-width: 40px;
|
--ebk-transaction-date-width: 40px;
|
||||||
--ebk-transaction-day-font-size: 24px;
|
--ebk-transaction-day-font-size: 24px;
|
||||||
--ebk-transaction-day-of-week-font-size: 19px;
|
--ebk-transaction-day-of-week-font-size: 19px;
|
||||||
|
--ebk-transaction-calendar-alternate-date-font-size: 19px;
|
||||||
--ebk-transaction-calendar-amount-font-size: 19px;
|
--ebk-transaction-calendar-amount-font-size: 19px;
|
||||||
--ebk-transaction-calendar-daily-amounts-height: 85px;
|
--ebk-transaction-calendar-daily-amounts-height: 85px;
|
||||||
|
--ebk-transaction-calendar-with-alternate-date-daily-amounts-height: 115px;
|
||||||
--ebk-transaction-account-arrow-font-size: 19px;
|
--ebk-transaction-account-arrow-font-size: 19px;
|
||||||
--ebk-transaction-account-arrow-margin-top: -4px;
|
--ebk-transaction-account-arrow-margin-top: -4px;
|
||||||
--ebk-transaction-tag-icon-font-size: 32px;
|
--ebk-transaction-tag-icon-font-size: 32px;
|
||||||
|
|||||||
@@ -270,6 +270,10 @@ html[dir="rtl"] i.icon.icon-with-direction {
|
|||||||
transform: scaleX(-1);
|
transform: scaleX(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.datetime-picker-alternate-date {
|
||||||
|
font-size: var(--ebk-datetime-picker-alternate-date-font-size);
|
||||||
|
}
|
||||||
|
|
||||||
/** Replacing the default style of @vuepic/vue-datepicker **/
|
/** Replacing the default style of @vuepic/vue-datepicker **/
|
||||||
.dp__theme_light {
|
.dp__theme_light {
|
||||||
--dp-primary-color: #c67e48;
|
--dp-primary-color: #c67e48;
|
||||||
|
|||||||
@@ -1880,7 +1880,19 @@ init(props);
|
|||||||
--dp-primary-text-color: rgb(var(--v-theme-primary));
|
--dp-primary-text-color: rgb(var(--v-theme-primary));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.transaction-calendar-container .dp__main.transaction-calendar-with-alternate-date .dp__calendar .dp__calendar_row {
|
||||||
|
--dp-cell-size: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
.transaction-calendar-container .dp__main .dp__calendar .dp__calendar_row > .dp__calendar_item {
|
.transaction-calendar-container .dp__main .dp__calendar .dp__calendar_row > .dp__calendar_item {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.transaction-calendar-container .dp__main .dp__calendar .dp__calendar_row > .dp__calendar_item .transaction-calendar-daily-amounts > span.transaction-calendar-alternate-date {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transaction-calendar-container .dp__main .dp__calendar .dp__calendar_row > .dp__calendar_item .transaction-calendar-daily-amounts > span.transaction-calendar-daily-amount {
|
||||||
|
font-size: 0.95rem;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1632,6 +1632,10 @@ html[dir="rtl"] .list.transaction-info-list li.transaction-info .transaction-foo
|
|||||||
--dp-primary-text-color: var(--f7-theme-color);
|
--dp-primary-text-color: var(--f7-theme-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.transaction-calendar-container .dp__main.transaction-calendar-with-alternate-date .dp__calendar .dp__calendar_row {
|
||||||
|
--dp-cell-size: var(--ebk-transaction-calendar-with-alternate-date-daily-amounts-height);
|
||||||
|
}
|
||||||
|
|
||||||
.transaction-calendar-container .dp__main .dp__calendar .dp__calendar_row > .dp__calendar_item .transaction-calendar-daily-amounts {
|
.transaction-calendar-container .dp__main .dp__calendar .dp__calendar_row > .dp__calendar_item .transaction-calendar-daily-amounts {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -1673,6 +1677,10 @@ html[dir="rtl"] .list.transaction-info-list li.transaction-info .transaction-foo
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.transaction-calendar-container .dp__main .dp__calendar .dp__calendar_row > .dp__calendar_item .transaction-calendar-daily-amounts > span.transaction-calendar-alternate-date {
|
||||||
|
font-size: var(--ebk-transaction-calendar-alternate-date-font-size);
|
||||||
|
}
|
||||||
|
|
||||||
.transaction-calendar-container .dp__main .dp__calendar .dp__calendar_row > .dp__calendar_item .transaction-calendar-daily-amounts > span.transaction-calendar-daily-amount {
|
.transaction-calendar-container .dp__main .dp__calendar .dp__calendar_row > .dp__calendar_item .transaction-calendar-daily-amounts > span.transaction-calendar-daily-amount {
|
||||||
font-size: var(--ebk-transaction-calendar-amount-font-size);
|
font-size: var(--ebk-transaction-calendar-amount-font-size);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user