Number of Days in Month for templating?

Is there a way that I can get the number of days in a month? I’m trying to do a calc of the progress into the month to calculate the amount of % into the month for data usage.

You could try creating a template sensor to hold the value for the number of days in the current month. Be sure to check out the Template Sensor documentation if you haven’t worked with these before, particularly the note about sensors that don’t have a corresponding entity - you’ll want to use the sensor.date as shown in the example at the bottom of the page.

Here is a potential template that might work for this sensor:

{% if now().month in [1,3,5,7,8,10,12] %}
  31
{% elif now().month in [4,6,9,11] %}
  30
{% elif now().month == 2 and ((now().year-2000) % 4 > 0) %}
  28
{% elif now().month == 2 and ((now().year-2000) % 4 == 0) %}
  29
{% endif %}

Hope this helps!

5 Likes

How about this:

  1. You know today’s date. now()
  2. Take the month part of today’s date now().month
  3. Add 1 now().month+1 this is next month (special case where we are in december needs attention
  4. Take the first of next month.
  5. Subtract 1 to get the last day of this month.
  6. The day part of the resulting date will tell us the number of days in this month.

I don’t prefer to implement date-time-related things by hand because it can be easily bad.
E.g. @Brett_C, you missed handling some exceptions (rules)

Here is a Python’s date-time library-based solution:

{% set dt = now() %}
{{ (dt.replace(month=dt.month % 12 + 1, day=1) - timedelta(days=1)).day }}

(based on How do we determine the number of days for a given month in python - Stack Overflow, that is quite similar to @nickrout’s solution)

- platform: command_line
  name: Days In Current Month
  command: cal $(date +"%m %Y") | awk 'NF {DAYS = $NF}; END {print DAYS}'
  scan_interval: 21600

This has worked for several; years without a glitch.

1 Like

I think this template will work even in December

{{ ((now().replace(day=1) + timedelta(days = 32)).replace(day=1) -timedelta(days=1)).day}}
1 Like

Is it possible to get days in last month?

Same approach. Take the first day of the current month, go back one day and you’ll be at the last day of last month. And that tells you how many days were in that month.

I can’t get it to work. Can you help me please? :grin:

I want to get how many days it was in last month. So today the sensor should show 31.

{{ ((now().replace(day=1) -timedelta(days=1))).day}}
2 Likes

This shows 30 for May.

Edit: didn’t notice that it was a reply. My bad… Sorry.

Did you read the question he was answering? The question was “how do I get the number of days last month”. And he replied with that template. April has 30 days.

1 Like

@nickrout @petro

perhaps you could help me further, I would be very happy, but please don’t stone me.

Actually, I would like to have the exact pro rata cent amount per day for my monthly basic amount of €11.40/month (electricity), so that when I look at the day, month or year, I always find the correct value aggregated upwards. Perhaps that’s the background :slight_smile:.

I have understood that the easiest way to generate the current days of the current month is via python.

I have currently created 2 sensors to bring this daily rate into my energy dashboard:

template:
  - sensor:
      # Strom Sensoren
    - name: "Platzhalter Verbrauch Grundpreis"
      unit_of_measurement: kWh
      device_class: energy
      state: 0
      state_class: total
    
    - name: "Grundpreis"
      state_class: total_increasing
      unit_of_measurement: EUR
      device_class: monetary
      state: "{{ ((now().strftime('%j')|float - 138) + (now().year - 2023) * 365) * 0.3748 }}"
      

In the end, it’s all about the (cent in €):

0.3748

In my opinion, this is not quite so correct, as these are calculated on the basis of the days of the year and as the months always have different numbers of days, the monthly value is not correct.

Example:

  • January 2024:

Basic fee €11.40/month / number of days in the month 31 days = 0.3748€

:slight_smile: - in the month it fits

  • February 2024:

Basic fee €11.40/month / number of days in the month 29 days = 0,3931 €

:frowning: - it doesn’t currently fit in this month and I wanted to tackle this with the approach already discussed above and am somehow stuck.

and as I’m writing all this, I’m coming up with lots of ideas about what a great solution would look like for me. But perhaps let’s move on to the actual topic.

What have I already done? I have under

config/

created a /python_scripts folder and already put a days_in_month.py in it. I understood the above discussion to mean that this is already the python script that returns the current days of the month:

{% set dt = now() %}
{{ (dt.replace(month=dt.month % 12 + 1, day=1) - timedelta(days=1)).day }}

But I certainly misunderstood that. Is it even possible to use it the way I want to?

I wanted to turn this value into a sensor:

command_line:
  - binary_sensor:
      name: "Anzahl Tage (aktueller Monat)"
      unique_id: "anzahl_tage_aktueller_monat"
      command: "python3 /python_scripts/days_in_month.py"
      value_template: '{{ value_json ["Anzahl Tage"] }}'

and then continue working with this sensor sometime later, my thought was to then use an input_number_entity to set the monthly base fee and then divide the monthly base fee by the monthly base fee as in the example above (February).

Then I finally have the value I need and would like to see the result here instead of today’s

0.3748

state: "{{ ((now().strftime('%j')|float - 138) + (now().year - 2023) * 365) * THE RESULT OF THE WHOLE DECLARATION (in Feb. the value would be drawn here: 0,3931)

Hopefully I’ve made enough effort to make it “easy” to understand, but I would be very happy if you or anyone else could help me with this, I just can’t get any further.

Neither the sensor nor the value is displayed.

Thank you very much
Seger

edit: wow, I just threw it into the template and it already shows the 31 days, does it already access phyton that easily? You can explain it to me if you want :slight_smile: and if I’m totally stupid …

edit2:
maybe it is:

state: “{{ ((now().strftime(‘%j’)|float - 138) + (now().year - 2023) * 365) * (11.40/(dt.replace(month=dt.month % 12 + 1, day=1) - timedelta(days=1)).day) }}”

??? Now I should still get the 11.40€/month from an input_number helper. Can someone follow me igrend and am I right!? haha

edit3: ?!

state: "{{ ((now().strftime('%j')|float - 138) + (now().year - 2023) * 365) * (11.40/((now().replace(day=1) + timedelta(days = 32)).replace(day=1) -timedelta(days=1)).day) }}"

Sorry I have no idea what you are trying to achieve.

Hello @Seger85 ,
have you found a solution in the meantime? I came across your entry because I (also) want to display: current costs per month (working price & pro rata basic price) vs. pro rata discount, each for the current month. Ideally also a delta of the two.

German: Hallo, hast du inzwischen eine Lösung gefunden? Bin auf deinen Eintrag gestoßen, da ich mir (auch) anzeigen lassen wissen: momentane Kosten pro Monat (Arbeitspreis & anteiliger Grundpreis) vs. anteiliger Abschlag, jeweils für den laufenden Monat. Idealerweise auch ein Delta der beiden.

Please keep it in English. The number of days in this month was alreay in the post above. What it does is go to the first day of the next month, subtract one day and take the day numer of that. So divide the month price by this number to get the day price in this month. This gives the day number:

So to get the dayprice based on 11.40 per month:

{% set dt = now() %}
{% set days = (dt.replace(month=dt.month % 12 + 1, day=1) - timedelta(days=1)).day %}
{{ 11.40 / days }}
2 Likes