Show Start and End Times in Local Time Zone
- Page Owner: Not Set
- Last Reviewed: 2025-11-05
We have an Event Page that has DateTime properties for both the start and end of an event. The server stores these properties in UTC, but we want the dates and times shown on the page to be in the user's local time zone.
For our page, the start and end dates are on one line while the start and end times are on a new line below, so we will need to use four <time> tags. We will use the class attribute to define what each <time> tag represents. All of the <time> tags will have their datetime attribute set to the corresponding start or end DateTime value in UTC in ISO 8601 format (with milliseconds and time zone offset). We will use JavaScript to read these attributes and convert to the user's local time zone.
We add <time> tags for both the start and end dates. Since our solution requires JavaScript for converting to the user's local time, we set the text content for the <time> tags to the start and end dates in UTC. Then, we add <time> tags for both the start and end times. Again, we set the text content for the <time> tags to the start and end times in UTC.
View
<div class="event-page__date">
@{
var startDateTimeUtc = Model?.Page.StartDateTime.ToUniversalTime();
var endDateTimeUtc = Model?.Page.EndDateTime.ToUniversalTime();
<h3>
<time class="startDate" datetime="@startDateTimeUtc?.ToString("yyyy-MM-ddTHH:mm:ss.fffzzz")">@startDateTimeUtc?.ToLongDateString()</time>
<time class="endDate" datetime="@endDateTimeUtc?.ToString("yyyy-MM-ddTHH:mm:ss.fffzzz")">@endDateTimeUtc?.ToLongDateString()</time>
</h3>
<p>
<b>
<time class="startTime" datetime="@startDateTimeUtc?.ToString("yyyy-MM-ddTHH:mm:ss.fffzzz")">@startDateTimeUtc?.ToString("h:mm tt") UTC</time>
<time class="endTime" datetime="@endDateTimeUtc?.ToString("yyyy-MM-ddTHH:mm:ss.fffzzz")">@endDateTimeUtc?.ToString("h:mm tt") UTC</time>
</b>
</p>
}
</div>
Now, we use JavaScript to grab the start and end datetimes from the <time> elements and build Date objects. While the time value at the heart of a Date object in JavaScript is UTC, the basic methods to fetch the date and time or its components all work in the local (i.e., host system) time zone and offset. We add a DateTimeFormat object for formatting both the dates and times to our liking and then simply set the textContent for each <time> element to the formatted value. Finally, we check if the formatted start and end dates or formatted start and end times (that have now been converted to local time) are equal. If so, remove the second element since it is unnecessary.
JavaScript
const eventPageDateElement = document.querySelector('.event-page__date');
if (eventPageDateElement) {
const dateFormatter = new Intl.DateTimeFormat('en-US', {
weekday: 'long',
month: 'long',
day: 'numeric',
year: 'numeric'
});
const startDateElement = eventPageDateElement.querySelector('.startDate');
const endDateElement = eventPageDateElement.querySelector('.endDate');
const startDateTime = new Date(startDateElement?.dateTime);
const endDateTime = new Date(endDateElement?.dateTime);
startDateElement.textContent = dateFormatter.format(startDateTime);
endDateElement.textContent = dateFormatter.format(endDateTime);
if (startDateElement.textContent == endDateElement.textContent) {
endDateElement.remove();
}
const timeFormatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: '2-digit',
timeZoneName: 'short'
});
const startTimeElement = eventPageDateElement.querySelector('.startTime');
const endTimeElement = eventPageDateElement.querySelector('.endTime');
startTimeElement.textContent = timeFormatter.format(startDateTime);
endTimeElement.textContent = timeFormatter.format(endDateTime);
if (startTimeElement.textContent == endTimeElement.textContent) {
endTimeElement.remove();
}
}
For the finishing touch, we will use CSS to add a dash (-) between the start and end <time> elements (but only if they both exist). If only one exists, the CSS rule will not apply and the dash pseudo element will not be added.
CSS
.event-page__date {
time:first-child:not(:empty) + time:not(:empty):before {
content: "- ";
}
}