diff --git a/frontend/src/metabase/lib/formatting/date.js b/frontend/src/metabase/lib/formatting/date.js index 009863ed4f005e7e70bfe86c6d312b018e89d645..a57995e92181449d06a4e31364da3be774d5979f 100644 --- a/frontend/src/metabase/lib/formatting/date.js +++ b/frontend/src/metabase/lib/formatting/date.js @@ -13,7 +13,7 @@ export type DateStyle = | "D MMMM, YYYY" | "dddd, MMMM D, YYYY"; -export type TimeStyle = "h:mm A" | "k:mm"; +export type TimeStyle = "h:mm A" | "k:mm" | "h A"; export type MomentFormat = string; // moment.js format strings export type DateFormat = MomentFormat; @@ -25,7 +25,6 @@ const DEFAULT_DATE_FORMATS: { [unit: DatetimeUnit]: MomentFormat } = { year: "YYYY", quarter: "[Q]Q - YYYY", "minute-of-hour": "m", - "hour-of-day": "h A", "day-of-week": "dddd", "day-of-month": "D", "day-of-year": "DDD", @@ -86,7 +85,12 @@ export function getDateFormatFromStyle( return replaceSeparators(style); } -const UNITS_WITH_HOUR: DatetimeUnit[] = ["default", "minute", "hour"]; +const UNITS_WITH_HOUR: DatetimeUnit[] = [ + "default", + "minute", + "hour", + "hour-of-day", +]; const UNITS_WITH_DAY: DatetimeUnit[] = [ "default", "minute", diff --git a/frontend/src/metabase/visualizations/lib/settings/column.js b/frontend/src/metabase/visualizations/lib/settings/column.js index e72aa5bf4acbb328a2cb26a81b04dc6f7752f396..d0bd7dc2c37589633a2efcf9ebb7a751e5bf071d 100644 --- a/frontend/src/metabase/visualizations/lib/settings/column.js +++ b/frontend/src/metabase/visualizations/lib/settings/column.js @@ -26,7 +26,6 @@ import { numberFormatterForOptions, } from "metabase/lib/formatting"; import { - DEFAULT_DATE_STYLE, getDateFormatFromStyle, hasDay, hasHour, @@ -108,6 +107,13 @@ function getDateStyleOptionsForUnit( abbreviate?: boolean = false, separator?: string, ) { + // hour-of-day shouldn't have any date style. It's handled as a time instead. + // Other date parts are handled as dates, but hour-of-day needs to use the + // time settings for 12/24 hour clock. + if (unit === "hour-of-day") { + return []; + } + const options = [ dateStyleOption("MMMM D, YYYY", unit, null, abbreviate, separator), dateStyleOption("D MMMM, YYYY", unit, null, abbreviate, separator), @@ -177,7 +183,12 @@ export const DATE_COLUMN_SETTINGS = { date_style: { title: t`Date style`, widget: "select", - default: DEFAULT_DATE_STYLE, + getDefault: ({ unit }: Column) => { + // Grab the first option's value. If there were no options (for + // hour-of-day probably), use an empty format string instead. + const [{ value = "" } = {}] = getDateStyleOptionsForUnit(unit); + return value; + }, isValid: ({ unit }: Column, settings: ColumnSettings) => { const options = getDateStyleOptionsForUnit(unit); return !!_.findWhere(options, { value: settings["date_style"] }); @@ -257,6 +268,9 @@ export const DATE_COLUMN_SETTINGS = { getProps: (column: Column, settings: ColumnSettings) => ({ options: [ timeStyleOption("h:mm A", "12-hour clock"), + ...(column.unit === "hour-of-day" + ? [timeStyleOption("h A", "12-hour clock without minutes")] + : []), timeStyleOption("k:mm", "24-hour clock"), ], }), diff --git a/frontend/test/metabase/lib/formatting.unit.spec.js b/frontend/test/metabase/lib/formatting.unit.spec.js index d125f1294d118b91e6ca6cf8ee7866e593f2efef..8d699440e4df69118ef1e844f83a38a9374c5d95 100644 --- a/frontend/test/metabase/lib/formatting.unit.spec.js +++ b/frontend/test/metabase/lib/formatting.unit.spec.js @@ -200,6 +200,32 @@ describe("formatting", () => { }), ).toEqual("foobar@example.com"); }); + it("should display hour-of-day with 12 hour clock", () => { + expect( + formatValue(24, { + date_style: null, + time_enabled: "minutes", + time_style: "h:mm A", + column: { + base_type: "type/DateTime", + unit: "hour-of-day", + }, + }), + ).toEqual("12:00 AM"); + }); + it("should display hour-of-day with 24 hour clock", () => { + expect( + formatValue(24, { + date_style: null, + time_enabled: "minutes", + time_style: "k:mm", + column: { + base_type: "type/DateTime", + unit: "hour-of-day", + }, + }), + ).toEqual("24:00"); + }); }); describe("formatUrl", () => { diff --git a/frontend/test/metabase/visualizations/lib/settings/column.unit.spec.js b/frontend/test/metabase/visualizations/lib/settings/column.unit.spec.js index b0258af57cad993faa26d1fe414e851284937da7..9b06eeae939cc8568130d3cbfc109a3c09430c24 100644 --- a/frontend/test/metabase/visualizations/lib/settings/column.unit.spec.js +++ b/frontend/test/metabase/visualizations/lib/settings/column.unit.spec.js @@ -96,4 +96,19 @@ describe("column settings", () => { const computed = getComputedSettings(defs, series, stored); expect(computed.column(series[0].data.cols[0]).currency).toEqual("BTC"); }); + it("should set a time style but no date style for hour-of-day", () => { + const series = seriesWithColumn({ + unit: "hour-of-day", + base_type: "type/DateTime", + special_type: undefined, + }); + const defs = { ...columnSettings() }; + const computed = getComputedSettings(defs, series, {}); + const { time_enabled, time_style, date_style } = computed.column( + series[0].data.cols[0], + ); + expect(time_enabled).toEqual("minutes"); + expect(time_style).toEqual("h:mm A"); + expect(date_style).toEqual(""); + }); });