このコミットが含まれているのは:
2026-10-28 21:58:24 +09:00
コミット 97e769248f
6個のファイルの変更、90行の追加、23行の削除
+62
ファイルの表示
@@ -392,12 +392,66 @@ export const countsDetailClipboardTable = (
}
const zonedCalendarDate = (
year: number, month: number, day: number, hour: number, timezone: string,
): Date => {
const target = Date.UTC (year, month - 1, day, hour)
const formatter = new Intl.DateTimeFormat ('en-US-u-ca-gregory-nu-latn', {
timeZone: timezone, year: 'numeric', month: '2-digit', day: '2-digit',
hour: '2-digit', minute: '2-digit', second: '2-digit', hourCycle: 'h23' })
const align = (date: Date) => {
const parts = formatter.formatToParts (date)
const part = (type: string) => Number (
parts.find (entry => entry.type === type)?.value ?? 0)
const actual = Date.UTC (part ('year'), part ('month') - 1, part ('day'),
part ('hour'), part ('minute'), part ('second'))
return new Date (date.getTime () + target - actual)
}
return align (align (new Date (target)))
}
const countsDateValue = (
value: string, grain: string, locale: LocaleCode, timezone: string,
): string | null => {
const patterns = {
year: /^(\d{4})$/, quarter: /^(\d{4})-Q([1-4])$/,
month: /^(\d{4})-(\d{2})$/, week: /^(\d{4})-W(\d{2})$/,
day: /^(\d{4})-(\d{2})-(\d{2})$/,
hour: /^(\d{4})-(\d{2})-(\d{2}) (\d{2}):00$/ }
const pattern = patterns[grain as keyof typeof patterns]
const match = pattern == null ? null : value.match (pattern)
if (match == null) return null
const year = Number (match[1])
const weekStart = grain === 'week' ? new Date (Date.UTC (year, 0, 4)
- ((new Date (Date.UTC (year, 0, 4)).getUTCDay () + 6) % 7) * 86_400_000
+ (Number (match[2]) - 1) * 7 * 86_400_000) : null
const calendarYear = weekStart?.getUTCFullYear () ?? year
const month = weekStart == null
? (grain === 'quarter' ? (Number (match[2]) - 1) * 3 + 1
: (grain === 'month' || grain === 'day' || grain === 'hour'
? Number (match[2]) : 1))
: weekStart.getUTCMonth () + 1
const day = weekStart?.getUTCDate ()
?? (grain === 'day' || grain === 'hour' ? Number (match[3]) : 1)
const hour = grain === 'hour' ? Number (match[4]) : 12
const date = zonedCalendarDate (calendarYear, month, day, hour, timezone)
const unknown = ({ year: 'month', quarter: 'day', month: 'day', week: 'hour',
day: 'hour', hour: 'minute' } as const)[grain as keyof typeof patterns]
const formatted = localisedDateString (date, locale, unknown, timezone)
return grain === 'quarter' ? `${formatted} Q${match[2]}`
: (grain === 'week' ? `${formatted} W${match[2]}` : formatted)
}
export const countsSummaryValue = (
value: string | number | null,
axis: CountsAxis,
index: number,
data: CountsResult,
locale: LocaleCode,
timezone = 'UTC',
): string => {
const message = (key: string, values?: Record<string, string | number>) =>
translateUIMessage (key, 'counts', locale, values).text
@@ -414,5 +468,13 @@ export const countsSummaryValue = (
if (axis.field === 'event_type') return message (`events.${value}`)
if (axis.field === 'category' || axis.field === 'tag_category')
return message (`common:categories.${value}`)
const dateAxis = axis.field.endsWith ('_at')
|| axis.field.startsWith ('original_created_')
const grain = axis.grain ?? (dateAxis ? 'month' : null)
if (grain != null)
{
const date = countsDateValue (String (value), grain, locale, timezone)
if (date != null) return date
}
return String (value)
}