This post piggybacks on my earlier post "Print raw values from Smart Date fields in Twig templates - Drupal 8+".
The Drupal Smart Date module allows users to choose a timezone for each date entered in a Smart Date field. One of my clients has a site with an event content type that uses a Smart Date field, and they needed event dates and times to display in the actual timezone entered. However, no matter what timezone they chose, Drupal was displaying the dates in the site's default timezone, or in the case of logged-in users, the user-chosen timezone, if they'd set one.
To fix this, you have to set timezones for your dates in your Twig templates. The Twig date filter accepts a second parameter which is an explicitly declared timezone (you can find the list of supported timezones here).
So we just need to get the timezone value from the Smart Date field and pass it to the date filter on each date that we print in our Twig templates.
This is where you need to be careful. You can get a timezone value in the correct format by passing the value 'e'
to the |date
filter, but this won't be the actual timezone value entered in the field, but the Drupal-converted value. Confusing? Yes.
The value we want from the Smart Date field is .timezone
. Let's say you have a field called Event Dates on a node. In your Twig template, the timezone value would be gotten from that field by printing {{ node.field_event_dates.timezone }}
. This gives you a value such as "America/New_York".
You can then either pass that value to your date filter as is, or create a variable if you need to use it multiple places in your template:
// using the start value of the first date in a multiple-value or recurring Smart Date field
{{ node.field_event_dates[0].value|date('F j, Y', node.field_event_dates[0].timezone) }}
{% set timezone = node.field_event_dates[0].timezone %}
{{ node.field_event_dates[0].value|date('F j, Y', timezone) }}
There are a few gotchas. One is, if your Smart Date field is recurring or has multiple values, you may have to do some work to loop over the values and get the ones that you need for your particular situation. That's beyond the scope of this post.
Secondly, and very importantly, if the date is entered in the site default timezone, the .timezone
value will be null. Let's say your site default timezone is set to America/New York, and you enter data in a Smart Date field, leaving the timezone set to that default value. You might think that the .timezone
value for that date would be 'America/New_York'. But no, it's nothing at all.
This is important to know, because the site default timezone is the default value for Smart Date fields.
If you need to show the timezone for dates entered using the site default, you'll have to specifically set that value in your template, e.g.:
{% if node.field_event_dates[0].timezone == '' %}
{% set timezone = 'America/New_York' %}
{% else %}
{% set timezone = node.field_event_dates[0].timezone %}
{% endif %}