Time formatting in custom button card

I would like to show hourly forecast information using custom button cards. That works fine, but formatting the time of the forecast gives errors because the JS functions are not accepted within the custom button card. But making a sensor for each forecast time solely to format it seems overkill.
Is there a way to format datetime string in the custom button card?

I am new here, so if this is the wrong place to ask this question, please let me know.

In response to Pieter more details:

I have created my own forecast overview to have more control over it (things I missed in the existing controls) Besides the current day overview, I show a 5 hour forecast (that’s where I ran into problems).

The dashboard view contains 5 custom button cards to show 5 hours of forecast, based on a template (see details of the code below).

The time is shown with

return states[entity.entity_id].attributes.forecast[variables.item].datetime;

This will return a datetime in the format 2023-01-03T22:00:00+00:00
I am not able to get it to a format like 22:00. All conversion functions are not accepted in the custom button card.
E.g. as_timestamp(states[‘weather.home_hourly’].attributes.forecast[1].datetime) | timestamp_custom(’%H:%M’)
or by using functions like as_local or strftime

As a workaround, I have created sensors to convert the value to the correct format. But now I need 5 sensors just for formatting.
Creating sensors solely for formatting seems not right to me (also because it is not limited to this example).
Are there options to format the date within the custom card button? Or are there better workarounds.

The code in the dashboard view:

  - type: horizontal-stack
	  - type: custom:button-card
		template: homekit_weather_detail
		entity: weather.home_hourly
		  item: 1
	  - type: custom:button-card
		template: homekit_weather_detail
		entity: weather.home_hourly
		  item: 2

The button card template contains:

    show_state: false
    show_label: true
    show_icon: false
    show_name: false
    show_entity_picture: true
      item: 0
        - background-color: var(--theme-sys-ha-secondary-background-color)
        - border-radius: 6px
        - border-style: 1px
        - border-color: var(--theme-sys-elevation-surface-primary5)
        - padding: 0
        - margin: 0
        - grid-template-areas: '"l" "i" "temp" "precip"'    
        - grid-template-columns: 1fr
        - grid-template-rows: min-content min-content min-content min-content
        - justify-content: center
        - width: 100%
        - width: 90%
          - text-align: center
          - font-size: 12px
          - font-weight: 300
          - margin-top: 5px
          - text-align: center
          - font-size: 10px
          - font-weight: 500

          - text-align: center
          - font-size: 10px
          - font-weight: 300
    entity_picture: >
        if ((states[entity.entity_id].attributes.forecast[variables.item].datetime > states["sun.sun"].attributes.next_rising) && (states[entity.entity_id].attributes.forecast[variables.item].datetime < states["sun.sun"].attributes.next_setting))
          return "/local/images/weather/" + states[entity.entity_id].attributes.forecast[variables.item].condition + ".svg";
          if (states[entity.entity_id].attributes.forecast[variables.item].condition  == 'partycloudy')
            return "/local/images/weather/partlycloudy-night.svg";
            if (states[entity.entity_id].attributes.forecast[variables.item].condition == 'sunny')
              return "/local/images/weather/clear-night.svg";
              return "/local/images/weather/" + states[entity.entity_id].attributes.forecast[variables.item].condition + ".svg";
    label: >
		return states[entity.entity_id].attributes.forecast[variables.item].datetime;
      temp: >
           return states[entity.entity_id].attributes.forecast[variables.item].temperature + entity.attributes.temperature_unit; 
      precip: >
           return states[entity.entity_id].attributes.forecast[variables.item].precipitation + " " + entity.attributes.precipitation_unit;

Such as?

Show us what you have so far, including typical sensor values.

The custom button card supports JS in many places, so it almost certainly is possible. Keep in mind JS doesnt have great built-in datetime formatting options, so you need to build it up yourself.


Hi Pieter, I’ve put additional info regarding your questions in the original post.

The functions I used
as_timestamp, | timestamp_custom(’%H:%M’), as_local or strftime
were not accepted in the custom card button.

For now I see two workarounds:

  • either format in sensors and use the sensor in the custom button card.
  • or create an automation where I format input_text help which I use in the custom button card
    But I would like to solve it within the custom button card without having to create unnecessary extra entities.

If I should/can use a different approach, please let me know.


These are HA templating functions. In the CBC you can only use JS. You need to do something like this (tested in a JS console):

var dt = new Date();
var time = now.toLocaleTimeString('default', {
  hour: '2-digit',
  minute: '2-digit',

There are many ways to do this… See: Get the Hours and Minutes from a Date in JavaScript | bobbyhadz.

Thanks for your help. I have tried your example (returning the time variable), but that gives an error (now not function existing). Also using the functions used on the site you referred to give errors. It seems that the functions used in CBC are limited.
I think I will stop searching for a solution within the CBC code and use my workaround. It is taking too much time searching sites and I am getting a bit frustrated :wink:
The workaround (sensor) works.
Thanks for looking into it. Can I close this topic or will that be done automatically?

I don’t think so, but those are standard JS functions that all browsers support.

I’m curious to see exactly what you tried and what the errors were.

It would be considered done when you mark a specific post as the solution, but people will still be able to reply. Moderators usually close heated posts (which this fortunately isn’t).

As an example, I use this piece of JS in a button of mine:

        return (new Date()).toLocaleDateString("en-ZA", {timeZone: variables.timezone});

I was searching for a similar solution, and while thoroughly reading the custom button card manual, I found that this can actually be achieved using the helpers function, see: GitHub - custom-cards/button-card: ❇️ Lovelace button-card for home assistant (scroll down a bit)

1 Like

Good to know, but it should be noted that at the time of writing that didn’t exist. It got introduced with v4.0.0 (2023-07-29).