Event Date and Time in Visitor’s Timezone

In the BricksLabs Facebook group a user asks:

Wondering if you have a way of displaying events in the users time zone in Bricks? The event would be a Metabox CPT.

This Pro tutorial provides the steps for showing the value of a Meta Box datetime type of custom field in visitor’s timezone.

For example, let’s say an event’s date and time has been set to 2024-10-31 10:30 with the WordPress site’s timezone set to Melbourne, Australia. When viewed from Melbourne, Australia, that event’s single page shows October 31, 2024 at 10:30 AM. When a visitor from NY, USA views the same page they would see October 31, 2024 at 7:30 PM.

Step 1

At Settings → General, set your business/site timezone city.

Step 2

Create your CPT and a corresponding field group with Meta Box.

Do NOT set the value to be saved as timestamp.

Create/edit your CPT posts and populate the field.

Step 3

Add the following in child theme‘s functions.php (w/o the opening PHP tag) or a code snippets plugin:

<?php
/**
 * Get event datetime and convert it to UTC ISO8601 format for HTML datetime attribute
 * 
 * @param int $post_id Post ID. If 0, uses current post ID
 * @return string ISO8601 formatted datetime in UTC or empty string if no date
 */
function bl_get_event_datetime( int $post_id = 0 ): string {
    // Use current post ID if none provided
    if ( ! $post_id ) {
        $post_id = get_the_ID();
    }
    
    // Get the stored datetime string (format: "2024-10-31 10:30")
    $datetime_str = get_post_meta( $post_id, 'event_datetime', true );
    
    // Return empty string if no datetime is set
    if ( empty( $datetime_str ) ) {
        return '';
    }
    
    // Create DateTime object in WordPress timezone (e.g., Australia/Melbourne)
    // This interprets the stored time as local WordPress timezone time
    $local_datetime = new DateTime( $datetime_str, wp_timezone() );
    
    // Convert to UTC for the HTML datetime attribute
    // This allows JavaScript to correctly convert to visitor's timezone
    $utc_datetime = clone $local_datetime;
    $utc_datetime->setTimezone( new DateTimeZone( 'UTC' ) );
    
    // Return in ISO8601 format (e.g., "2024-10-30T23:30:00+00:00")
    // This format is required for the HTML5 datetime attribute
    return $utc_datetime->format( 'c' );
}

/**
 * Allow <time> HTML tag in Bricks builder
 */
add_filter( 'bricks/allowed_html_tags', function( $allowed_html_tags ) {
    // Add <time> tag to allowed HTML tags
    $additional_tags = ['time'];

    // Merge with existing allowed tags and return
    return array_merge( $allowed_html_tags, $additional_tags );
} );

/**
 * Register function for use in Bricks builder
 */
add_filter( 'bricks/code/echo_function_names', function() {
    return [
        'bl_get_event_datetime',
    ];
} );

Replace event_datetime with the ID of your field.

Step 4

Edit your single CPT template with Bricks.

Add a Basic Text element for outputting the event’s date and time.

Set the text to:

{echo:bl_get_event_datetime}

Add this class: event-datetime

Add an attribute named datetime

Value:

{echo:bl_get_event_datetime}

At Settings (gear icon) → PAGE SETTINGS → CUSTOM CODE → Body (footer) scripts add:

<script>
/**
 * Convert UTC datetime to visitor's local timezone
 * Looks for elements with class 'event-datetime' and converts their datetime attributes
 * 
 * Example input: <time class="event-datetime" datetime="2024-10-30T23:30:00+00:00">
 * Example output: "October 31, 2024 at 10:30 AM" (for Melbourne visitor)
 */
document.addEventListener('DOMContentLoaded', () => {
    // Find all elements with class 'event-datetime'
    const eventDatetimes = document.querySelectorAll('.event-datetime');
    
    eventDatetimes.forEach(timeElement => {
        // Get UTC datetime from the HTML datetime attribute
        const utcDatetime = timeElement.getAttribute('datetime');
        
        // Create Date object from UTC datetime string
        // JavaScript automatically converts this to local timezone
        const localDate = new Date(utcDatetime);
        
        // Configure datetime display format
        const options = {
            year: 'numeric',
            month: 'long',
            day: 'numeric',
            hour: 'numeric',
            minute: '2-digit',
            hour12: true,          // Use 12-hour format (AM/PM)
            // timeZoneName: 'short'  // Show timezone abbreviation (e.g., EST, GMT+7)
        };
        
        // Convert to localized string using browser's locale
        // This automatically uses the visitor's locale and timezone
        timeElement.textContent = localDate.toLocaleString(
            navigator.language, // Use visitor's browser language
            options
        );
    });
});
</script>