Skip to content
15 changes: 2 additions & 13 deletions src/common/datetime/format_date.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,24 +97,13 @@ const formatDateNumericMem = memoizeOne(
(locale: FrontendLocaleData, serverTimeZone: string) => {
const localeString =
locale.date_format === DateFormat.system ? undefined : locale.language;

if (
locale.date_format === DateFormat.language ||
locale.date_format === DateFormat.system
) {
return new Intl.DateTimeFormat(localeString, {
year: "numeric",
month: "numeric",
day: "numeric",
timeZone: resolveTimeZone(locale.time_zone, serverTimeZone),
});
}
const timeZone = resolveTimeZone(locale.time_zone, serverTimeZone);

return new Intl.DateTimeFormat(localeString, {
year: "numeric",
month: "numeric",
day: "numeric",
timeZone: resolveTimeZone(locale.time_zone, serverTimeZone),
timeZone,
});
}
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import { resolveTimeZone } from "../common/datetime/resolve-time-zone";
import { fireEvent } from "../common/dom/fire_event";
import { configContext, internationalizationContext } from "../data/context";
import {
CLOCK_CARD_DATE_PARTS,
formatClockCardDate,
} from "../panels/lovelace/cards/clock/clock-date-format";
import type { ClockCardDatePart } from "../panels/lovelace/cards/types";
DATE_FORMAT_PARTS,
formatDateFromParts,
} from "../panels/lovelace/cards/date-format";
import type { DateFormatPart } from "../panels/lovelace/cards/types";
import type { HomeAssistant, ValueChangedEvent } from "../types";
import "./chips/ha-assist-chip";
import "./chips/ha-chip-set";
Expand All @@ -23,31 +23,31 @@ import "./ha-input-helper-text";
import type { PickerComboBoxItem } from "./ha-picker-combo-box";
import "./ha-sortable";

type ClockDatePartSection = "weekday" | "day" | "month" | "year" | "separator";
type DateFormatPartSection = "weekday" | "day" | "month" | "year" | "separator";

type ClockDateSeparatorPart = Extract<
ClockCardDatePart,
type DateFormatSeparatorPart = Extract<
DateFormatPart,
"separator-dash" | "separator-slash" | "separator-dot" | "separator-new-line"
>;

const CLOCK_DATE_PART_SECTION_ORDER: readonly ClockDatePartSection[] = [
const DATE_FORMAT_PART_SECTION_ORDER: readonly DateFormatPartSection[] = [
"day",
"month",
"year",
"weekday",
"separator",
];

const CLOCK_DATE_SEPARATOR_VALUES: Record<ClockDateSeparatorPart, string> = {
const DATE_FORMAT_SEPARATOR_VALUES: Record<DateFormatSeparatorPart, string> = {
"separator-dash": "-",
"separator-slash": "/",
"separator-dot": ".",
"separator-new-line": "",
};

const getClockDatePartSection = (
part: ClockCardDatePart
): ClockDatePartSection => {
const getDateFormatPartSection = (
part: DateFormatPart
): DateFormatPartSection => {
if (part.startsWith("weekday-")) {
return "weekday";
}
Expand All @@ -67,8 +67,8 @@ const getClockDatePartSection = (
return "separator";
};

interface ClockDatePartSectionData {
id: ClockDatePartSection;
interface DateFormatPartSectionData {
id: DateFormatPartSection;
title: string;
items: PickerComboBoxItem[];
}
Expand All @@ -81,20 +81,20 @@ interface ClockDatePartSectionData {
* pre-existing config authored outside the picker via YAML).
* The separator group is always kept.
*/
export const getAvailableClockDatePartSections = (
sections: ClockDatePartSectionData[],
export const getAvailableDateFormatPartSections = (
sections: DateFormatPartSectionData[],
value: string[],
excludeIndex?: number
): ClockDatePartSectionData[] => {
): DateFormatPartSectionData[] => {
const editedItem = excludeIndex != null ? value[excludeIndex] : undefined;
const editedSection = editedItem
? getClockDatePartSection(editedItem as ClockCardDatePart)
? getDateFormatPartSection(editedItem as DateFormatPart)
: undefined;

const usedSections = new Set<ClockDatePartSection>();
const usedSections = new Set<DateFormatPartSection>();

value.forEach((item) => {
const section = getClockDatePartSection(item as ClockCardDatePart);
const section = getDateFormatPartSection(item as DateFormatPart);

if (section !== "separator" && section !== editedSection) {
usedSections.add(section);
Expand All @@ -107,14 +107,14 @@ export const getAvailableClockDatePartSections = (
);
};

interface ClockDatePartValueItem {
interface DateFormatPartValueItem {
key: string;
item: string;
idx: number;
}

@customElement("ha-clock-date-format-picker")
export class HaClockDateFormatPicker extends LitElement {
@customElement("ha-date-format-parts-picker")
export class HaDateFormatPartsPicker extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;

@property({ type: Boolean, reflect: true }) public disabled = false;
Expand Down Expand Up @@ -143,7 +143,7 @@ export class HaClockDateFormatPicker extends LitElement {
const value = this._value;
const valueItems = this._getValueItems(value);
const sections = this._buildSections();
const pickerSections = getAvailableClockDatePartSections(
const pickerSections = getAvailableDateFormatPartSections(
sections,
value,
this._editIndex
Expand Down Expand Up @@ -171,7 +171,7 @@ export class HaClockDateFormatPicker extends LitElement {
<ha-chip-set>
${repeat(
valueItems,
(entry: ClockDatePartValueItem) => entry.key,
(entry: DateFormatPartValueItem) => entry.key,
({ item, idx }) => this._renderValueChip(item, idx, sections)
)}
${
Expand Down Expand Up @@ -207,7 +207,7 @@ export class HaClockDateFormatPicker extends LitElement {
}

private _getValueItems = memoizeOne(
(value: string[]): ClockDatePartValueItem[] => {
(value: string[]): DateFormatPartValueItem[] => {
const occurrences = new Map<string, number>();

return value.map((item, idx) => {
Expand All @@ -226,7 +226,7 @@ export class HaClockDateFormatPicker extends LitElement {
private _renderValueChip(
item: string,
idx: number,
sections: ClockDatePartSectionData[]
sections: DateFormatPartSectionData[]
) {
const label = this._getItemLabel(item, sections);
const isValid = !!label;
Expand Down Expand Up @@ -285,32 +285,33 @@ export class HaClockDateFormatPicker extends LitElement {
value.length === 0 ? undefined : value
);

private _buildSections(): ClockDatePartSectionData[] {
const itemsBySection: Record<ClockDatePartSection, PickerComboBoxItem[]> = {
weekday: [],
day: [],
month: [],
year: [],
separator: [],
};
private _buildSections(): DateFormatPartSectionData[] {
const itemsBySection: Record<DateFormatPartSection, PickerComboBoxItem[]> =
{
weekday: [],
day: [],
month: [],
year: [],
separator: [],
};

const previewDate = new Date();
const previewTimeZone = resolveTimeZone(
this._i18n.locale.time_zone,
this._hassConfig.config.time_zone
);

CLOCK_CARD_DATE_PARTS.forEach((part) => {
const section = getClockDatePartSection(part);
DATE_FORMAT_PARTS.forEach((part) => {
const section = getDateFormatPartSection(part);
const label =
this._i18n.localize(
`ui.panel.lovelace.editor.card.clock.date.parts.${part}`
`ui.panel.lovelace.editor.date_format.parts.${part}`
) ?? part;

const secondary =
section === "separator"
? CLOCK_DATE_SEPARATOR_VALUES[part as ClockDateSeparatorPart]
: formatClockCardDate(
? DATE_FORMAT_SEPARATOR_VALUES[part as DateFormatSeparatorPart]
: formatDateFromParts(
previewDate,
{ parts: [part] },
this._i18n.locale.language,
Expand All @@ -325,18 +326,18 @@ export class HaClockDateFormatPicker extends LitElement {
});
});

return CLOCK_DATE_PART_SECTION_ORDER.map((section) => ({
return DATE_FORMAT_PART_SECTION_ORDER.map((section) => ({
id: section,
title:
this._i18n.localize(
`ui.panel.lovelace.editor.card.clock.date.sections.${section}`
`ui.panel.lovelace.editor.date_format.sections.${section}`
) ?? section,
items: itemsBySection[section],
})).filter((section) => section.items.length > 0);
}

private _getSectionHeaders(
sections: ClockDatePartSectionData[]
sections: DateFormatPartSectionData[]
): { id: string; label: string }[] {
return sections.map((section) => ({
id: section.id,
Expand All @@ -345,7 +346,7 @@ export class HaClockDateFormatPicker extends LitElement {
}

private _getItems = memoizeOne(
(sections: ClockDatePartSectionData[]) =>
(sections: DateFormatPartSectionData[]) =>
(
searchString?: string,
section?: string
Expand Down Expand Up @@ -389,7 +390,7 @@ export class HaClockDateFormatPicker extends LitElement {

private _getItemLabel(
value: string,
sections: ClockDatePartSectionData[]
sections: DateFormatPartSectionData[]
): string | undefined {
for (const section of sections) {
const item = section.items.find((candidate) => candidate.id === value);
Expand Down Expand Up @@ -574,6 +575,6 @@ export class HaClockDateFormatPicker extends LitElement {

declare global {
interface HTMLElementTagNameMap {
"ha-clock-date-format-picker": HaClockDateFormatPicker;
"ha-date-format-parts-picker": HaDateFormatPartsPicker;
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { html, LitElement } from "lit";
import { customElement, property } from "lit/decorators";
import type { UiClockDateFormatSelector } from "../../data/selector";
import type { UiDateFormatPartsSelector } from "../../data/selector";
import type { HomeAssistant } from "../../types";
import "../ha-clock-date-format-picker";
import "../ha-date-format-parts-picker";

@customElement("ha-selector-ui_clock_date_format")
export class HaSelectorUiClockDateFormat extends LitElement {
@customElement("ha-selector-ui_date_format_parts")
export class HaSelectorUiDateFormatParts extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;

@property({ attribute: false }) public selector!: UiClockDateFormatSelector;
@property({ attribute: false }) public selector!: UiDateFormatPartsSelector;

@property() public value?: string | string[];

Expand All @@ -22,20 +22,20 @@ export class HaSelectorUiClockDateFormat extends LitElement {

protected render() {
return html`
<ha-clock-date-format-picker
<ha-date-format-parts-picker
.hass=${this.hass}
.value=${this.value}
.label=${this.label}
.helper=${this.helper}
.disabled=${this.disabled}
.required=${this.required}
></ha-clock-date-format-picker>
></ha-date-format-parts-picker>
`;
}
}

declare global {
interface HTMLElementTagNameMap {
"ha-selector-ui_clock_date_format": HaSelectorUiClockDateFormat;
"ha-selector-ui_date_format_parts": HaSelectorUiDateFormatParts;
}
}
2 changes: 1 addition & 1 deletion src/components/ha-selector/ha-selector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ const LOAD_ELEMENTS = {
location: () => import("./ha-selector-location"),
color_temp: () => import("./ha-selector-color-temp"),
ui_action: () => import("./ha-selector-ui-action"),
ui_clock_date_format: () => import("./ha-selector-ui-clock-date-format"),
ui_color: () => import("./ha-selector-ui-color"),
ui_date_format_parts: () => import("./ha-selector-ui-date-format-parts"),
ui_state_content: () => import("./ha-selector-ui-state-content"),
ui_time_format: () => import("./ha-selector-ui-time-format"),
};
Expand Down
6 changes: 3 additions & 3 deletions src/data/selector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ export type Selector =
| TTSVoiceSelector
| SerialPortSelector
| UiActionSelector
| UiClockDateFormatSelector
| UiColorSelector
| UiDateFormatPartsSelector
| UiStateContentSelector
| UiTimeFormatSelector
| BackupLocationSelector;
Expand Down Expand Up @@ -598,8 +598,8 @@ export interface UiActionSelector {
} | null;
}

export interface UiClockDateFormatSelector {
ui_clock_date_format: {} | null;
export interface UiDateFormatPartsSelector {
ui_date_format_parts: {} | null;
}

export interface UiColorExtraOption {
Expand Down
20 changes: 10 additions & 10 deletions src/panels/lovelace/cards/clock/hui-clock-card-analog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import "../../../../components/ha-marquee-text";
import type { HomeAssistant } from "../../../../types";
import type { ClockCardConfig } from "../types";
import {
formatClockCardDate,
getClockCardDateConfig,
hasClockCardDate,
formatDateFromParts,
getDateFormatConfig,
hasDateFormatParts,
resolveClockCardLocale,
} from "./clock-date-format";
} from "../date-format";

function romanize12HourClock(num: number) {
const numerals = [
Expand Down Expand Up @@ -119,7 +119,7 @@ export class HuiClockCardAnalog extends LitElement {
this._computeOffsets();
this._updateDate();

if (this.isConnected && hasClockCardDate(this.config)) {
if (this.isConnected && hasDateFormatParts(this.config)) {
this._startDateTick();
} else {
this._stopDateTick();
Expand Down Expand Up @@ -165,13 +165,13 @@ export class HuiClockCardAnalog extends LitElement {
}

private _updateDate() {
if (!this.config || !hasClockCardDate(this.config) || !this._language) {
if (!this.config || !hasDateFormatParts(this.config) || !this._language) {
this._date = undefined;
return;
}

const dateConfig = getClockCardDateConfig(this.config);
this._date = formatClockCardDate(
const dateConfig = getDateFormatConfig(this.config);
this._date = formatDateFromParts(
new Date(),
dateConfig,
this._language,
Expand All @@ -181,8 +181,8 @@ export class HuiClockCardAnalog extends LitElement {

private _computeClock = memoizeOne((config: ClockCardConfig) => {
const faceParts = config.face_style?.split("_");
const dateConfig = getClockCardDateConfig(config);
const showDate = hasClockCardDate(config);
const dateConfig = getDateFormatConfig(config);
const showDate = hasDateFormatParts(config);
const isLongDate =
dateConfig.parts.includes("month-long") ||
dateConfig.parts.includes("weekday-long");
Expand Down
Loading
Loading