Skip to content

Commit

Permalink
Additional relative time formats
Browse files Browse the repository at this point in the history
  • Loading branch information
breakthestatic committed Nov 27, 2024
1 parent 4655929 commit 97070e7
Show file tree
Hide file tree
Showing 9 changed files with 68 additions and 15 deletions.
26 changes: 21 additions & 5 deletions src/common/datetime/relative_time.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,40 @@ import memoizeOne from "memoize-one";
import type { FrontendLocaleData } from "../../data/translation";
import { selectUnit } from "../util/select-unit";

export enum RelativeTimeFormat {
relative = "long",
relative_short = "short",
relative_narrow = "narrow",
}

export type RelativeTimeStyle = `${RelativeTimeFormat}`;

export function isRelativeTimeFormat(
format: string
): format is RelativeTimeFormat {
return Object.keys(RelativeTimeFormat).includes(format as RelativeTimeFormat);
}

const formatRelTimeMem = memoizeOne(
(locale: FrontendLocaleData) =>
new Intl.RelativeTimeFormat(locale.language, { numeric: "auto" })
(locale: FrontendLocaleData, style: RelativeTimeStyle) =>
new Intl.RelativeTimeFormat(locale.language, { numeric: "auto", style })
);

export const relativeTime = (
from: Date,
locale: FrontendLocaleData,
to?: Date,
includeTense = true
includeTense = true,
format = RelativeTimeFormat.relative
): string => {
const diff = selectUnit(from, to, locale);
const style = RelativeTimeFormat[format];
if (includeTense) {
return formatRelTimeMem(locale).format(diff.value, diff.unit);
return formatRelTimeMem(locale, style).format(diff.value, diff.unit);
}
return Intl.NumberFormat(locale.language, {
style: "unit",
unit: diff.unit,
unitDisplay: "long",
unitDisplay: style,
}).format(Math.abs(diff.value));
};
15 changes: 13 additions & 2 deletions src/components/ha-relative-time.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import { parseISO } from "date-fns";
import type { PropertyValues } from "lit";
import { ReactiveElement } from "lit";
import { customElement, property } from "lit/decorators";
import { relativeTime } from "../common/datetime/relative_time";
import {

Check failure on line 5 in src/components/ha-relative-time.ts

View workflow job for this annotation

GitHub Actions / Lint and check format

Imports "RelativeTimeFormat" are only used as type
relativeTime,
RelativeTimeFormat,
} from "../common/datetime/relative_time";
import { capitalizeFirstLetter } from "../common/string/capitalize-first-letter";
import type { HomeAssistant } from "../types";

Expand All @@ -12,6 +15,8 @@ class HaRelativeTime extends ReactiveElement {

@property({ attribute: false }) public datetime?: string | Date;

@property({ attribute: false }) public format?: RelativeTimeFormat;

@property({ type: Boolean }) public capitalize = false;

private _interval?: number;
Expand Down Expand Up @@ -65,7 +70,13 @@ class HaRelativeTime extends ReactiveElement {
? parseISO(this.datetime)
: this.datetime;

const relTime = relativeTime(date, this.hass.locale);
const relTime = relativeTime(
date,
this.hass.locale,
undefined,
undefined,
this.format
);
this.innerHTML = this.capitalize
? capitalizeFirstLetter(relTime)
: relTime;
Expand Down
1 change: 1 addition & 0 deletions src/panels/lovelace/badges/hui-entity-badge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ export class HuiEntityBadge extends LitElement implements LovelaceBadge {
.hass=${this.hass}
.content=${this._config.state_content}
.name=${this._config.name}
.format=${this._config.format}
>
</state-display>
`;
Expand Down
2 changes: 2 additions & 0 deletions src/panels/lovelace/badges/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { ActionConfig } from "../../../data/lovelace/config/action";
import type { LovelaceBadgeConfig } from "../../../data/lovelace/config/badge";
import type { LegacyStateFilter } from "../common/evaluate-filter";
import type { Condition } from "../common/validate-condition";
import type { TimestampRenderingFormat } from "../components/types";
import type { EntityFilterEntityConfig } from "../entity-rows/types";
import type { DisplayType } from "./hui-entity-badge";

Expand Down Expand Up @@ -42,6 +43,7 @@ export interface EntityBadgeConfig extends LovelaceBadgeConfig {
tap_action?: ActionConfig;
hold_action?: ActionConfig;
double_tap_action?: ActionConfig;
format?: TimestampRenderingFormat;
/**
* @deprecated use `show_state`, `show_name`, `icon_type`
*/
Expand Down
1 change: 1 addition & 0 deletions src/panels/lovelace/cards/hui-tile-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ export class HuiTileCard extends LitElement implements LovelaceCard {
.hass=${this.hass}
.content=${this._config.state_content}
.name=${this._config.name}
.format=${this._config.format}
>
</state-display>
`;
Expand Down
1 change: 1 addition & 0 deletions src/panels/lovelace/cards/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,7 @@ export interface TileCardConfig extends LovelaceCardConfig {
icon_hold_action?: ActionConfig;
icon_double_tap_action?: ActionConfig;
features?: LovelaceCardFeatureConfig[];
format?: TimestampRenderingFormat;
}

export interface HeadingCardConfig extends LovelaceCardConfig {
Expand Down
21 changes: 15 additions & 6 deletions src/panels/lovelace/components/hui-timestamp-display.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ import { customElement, property, state } from "lit/decorators";
import { formatDate } from "../../../common/datetime/format_date";
import { formatDateTime } from "../../../common/datetime/format_date_time";
import { formatTime } from "../../../common/datetime/format_time";
import { relativeTime } from "../../../common/datetime/relative_time";
import {
isRelativeTimeFormat,
RelativeTimeFormat,
relativeTime,
} from "../../../common/datetime/relative_time";
import { capitalizeFirstLetter } from "../../../common/string/capitalize-first-letter";
import type { FrontendLocaleData } from "../../../data/translation";
import type { HomeAssistant } from "../../../types";
Expand All @@ -22,7 +26,7 @@ const FORMATS: {
datetime: formatDateTime,
time: formatTime,
};
const INTERVAL_FORMAT = ["relative", "total"];
const INTERVAL_FORMAT = [...Object.keys(RelativeTimeFormat), "total"];

@customElement("hui-timestamp-display")
class HuiTimestampDisplay extends LitElement {
Expand Down Expand Up @@ -112,10 +116,15 @@ class HuiTimestampDisplay extends LitElement {

private _updateRelative(): void {
if (this.ts && this.hass?.localize) {
this._relative =
this._format === "relative"
? relativeTime(this.ts, this.hass!.locale)
: relativeTime(new Date(), this.hass!.locale, this.ts, false);
this._relative = isRelativeTimeFormat(this._format)
? relativeTime(
this.ts,
this.hass!.locale,
undefined,
undefined,
this._format
)
: relativeTime(new Date(), this.hass!.locale, this.ts, false);

this._relative = this.capitalize
? capitalizeFirstLetter(this._relative)
Expand Down
2 changes: 2 additions & 0 deletions src/panels/lovelace/components/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ export interface ConditionalBaseConfig extends LovelaceCardConfig {

export const TIMESTAMP_RENDERING_FORMATS = [
"relative",
"relative_narrow",
"relative_short",
"total",
"date",
"time",
Expand Down
14 changes: 12 additions & 2 deletions src/state-display/state-display.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ import type { UpdateEntity } from "../data/update";
import { computeUpdateStateDisplay } from "../data/update";
import "../panels/lovelace/components/hui-timestamp-display";
import type { HomeAssistant } from "../types";
import {
TIMESTAMP_RENDERING_FORMATS,
type TimestampRenderingFormat,
} from "../panels/lovelace/components/types";

const TIMESTAMP_STATE_DOMAINS = ["button", "input_button", "scene"];

Expand Down Expand Up @@ -59,6 +63,8 @@ class StateDisplay extends LitElement {

@property({ attribute: false }) public name?: string;

@property({ attribute: false }) public format?: TimestampRenderingFormat;

@property({ type: Boolean, attribute: "dash-unavailable" })
public dashUnavailable?: boolean;

Expand All @@ -77,7 +83,10 @@ class StateDisplay extends LitElement {
const stateObj = this.stateObj;
const domain = computeStateDomain(stateObj);

if (content === "state") {
if (
content === "state" ||
(this.format && TIMESTAMP_RENDERING_FORMATS.includes(this.format))
) {
if (this.dashUnavailable && isUnavailableState(stateObj.state)) {
return "—";
}
Expand All @@ -90,7 +99,7 @@ class StateDisplay extends LitElement {
<hui-timestamp-display
.hass=${this.hass}
.ts=${new Date(stateObj.state)}
format="relative"
.format=${this.format}
capitalize
></hui-timestamp-display>
`;
Expand Down Expand Up @@ -133,6 +142,7 @@ class StateDisplay extends LitElement {
<ha-relative-time
.hass=${this.hass}
.datetime=${relativeDateTime}
.format=${this.format}
capitalize
></ha-relative-time>
`;
Expand Down

0 comments on commit 97070e7

Please sign in to comment.