Timezone

Fieldtype for storing timezone values with dynamic UTC offsets.

Timezone Fieldtype and Inputfield for ProcessWire

Module Name: FieldtypeTimezone / InputfieldTimezone
Author: Maxim Alex
Version: 1.0.0
License: Mozilla Public License 2.0
Icon: clock-o

Overview


Simple and reliable module for ProcessWire that provides timezone functionality. The module automatically calculates current UTC offsets taking into account Daylight Saving Time (DST).

✨ Key Features

  • Dynamic UTC offsets - automatic calculation of current offsets with DST support
  • Simplicity - no complex settings, works out of the box
  • Performance - intelligent caching (24 hours)
  • Reliability - strict validation at all levels
  • Complete coverage - all major world timezones
  • ProcessWire 3.x - full compatibility

Display Format


Timezones are displayed in the format:

Country → City (UTC+X)

Examples:

United States → New York (UTC-5)
Japan → Tokyo (UTC+9)
United Kingdom → London (UTC+0)
Australia → Sydney (UTC+11)

UTC offsets are calculated dynamically, so for timezones with DST the values change automatically:

  • America/New_York: UTC-5 in winter, UTC-4 in summer
  • Europe/London: UTC+0 in winter, UTC+1 in summer

Requirements


  • ProcessWire 3.0.0 or higher
  • PHP 8.1 or higher
  • InputfieldTimezone module (installs automatically)

Installation


Option 1: Via Git

cd /path/to/processwire/site/modules/
git clone https://github.com/mxmsmnv/FieldtypeTimezone.git

Option 2: Manual Installation

  1. Download the ZIP archive
  2. Extract to /site/modules/FieldtypeTimezone/
  3. Ensure the structure is correct:
   /site/modules/FieldtypeTimezone/
   ├── FieldtypeTimezone.module.php
   ├── InputfieldTimezone.module.php
   └── README.md

Module Activation

  1. Log in to your ProcessWire admin panel
  2. Go to ModulesSite
  3. Find FieldtypeTimezone and click Install
  4. InputfieldTimezone will be installed automatically

Usage


Creating a Field

  1. Go to SetupFieldsAdd New
  2. Enter field name (e.g., user_timezone)
  3. Select type Timezone
  4. Save the field
  5. Add the field to desired templates

No additional configuration required - everything works out of the box!

Working with the Field in Templates

Basic Usage

// Get timezone value
$timezone = $page->user_timezone;
echo $timezone; // Outputs: America/New_York

// Check for empty value
if ($page->user_timezone) {
    echo "Timezone: " . $page->user_timezone;
}

Working with DateTime

// Create DateTime object with user's timezone
if ($page->user_timezone) {
    $tz = new \DateTimeZone($page->user_timezone);
    $datetime = new \DateTime('now', $tz);

    echo "Current time in user's timezone: " . $datetime->format('F j, Y \a\t g:i A T');
    // Outputs: Current time in user's timezone: December 31, 2025 at 5:13 PM EST
}

Time Conversion

// Convert UTC time to user's timezone
function convertToUserTimezone($utcTime, $userTimezone) {
    $utc = new \DateTimeZone('UTC');
    $tz = new \DateTimeZone($userTimezone);

    $datetime = new \DateTime($utcTime, $utc);
    $datetime->setTimezone($tz);

    return $datetime->format('F j, Y \a\t g:i A T');
}

// Usage
$utcTime = '2025-12-31 18:30:00';
$localTime = convertToUserTimezone($utcTime, $page->user_timezone);
echo $localTime; // December 31, 2025 at 2:30 PM EST (for America/New_York)

Getting Timezone Information

// Get detailed timezone information
$fieldtype = $fields->get('user_timezone')->type;
$info = $fieldtype->getTimezoneInfo($page->user_timezone);

if ($info) {
    echo "Identifier: " . $info['identifier'] . "<br>";
    echo "Offset: " . $info['offset_formatted'] . "<br>";
    echo "Abbreviation: " . $info['abbreviation'] . "<br>";
}

Programmatic Value Setting

// Set timezone programmatically
$page->of(false);
$page->user_timezone = 'Europe/London';
$page->save('user_timezone');
$page->of(true);

// Or when creating a page
$newPage = new Page();
$newPage->template = 'user';
$newPage->parent = $pages->get('/users/');
$newPage->title = 'John Doe';
$newPage->user_timezone = 'Asia/Tokyo';
$newPage->save();

Displaying User's Current Time

// Current time widget
if ($user->timezone) {
    $tz = new \DateTimeZone($user->timezone);
    $now = new \DateTime('now', $tz);

    echo "<div>";
    echo "<strong>Your local time:</strong> ";
    echo $now->format('l, F j, Y - g:i A T');
    echo "</div>";
    // Outputs: Tuesday, December 31, 2025 - 5:13 PM EST
}

API Methods

getTimezoneInfo($timezone)

Get complete timezone information:

$fieldtype = $fields->get('timezone_field')->type;
$info = $fieldtype->getTimezoneInfo('America/New_York');

// Returns array:
// [
//     'identifier' => 'America/New_York',
//     'offset' => -18000,
//     'offset_formatted' => 'UTC-5',
//     'name' => 'America/New_York',
//     'abbreviation' => 'EST'
// ]

Usage Examples


Example 1: User Profile with Timezone

// In user profile template
<div>
    <h2><?= $page->title ?></h2>

    <?php if ($page->user_timezone): ?>
        <div>
            <strong>Timezone:</strong>
            <?php
            $tz = new \DateTimeZone($page->user_timezone);
            $now = new \DateTime('now', $tz);
            echo $page->user_timezone . ' (Current time: ' .
                 $now->format('g:i A') . ')';
            ?>
        </div>
    <?php endif; ?>
</div>

Example 2: Event Calendar

// Display event time in user's timezone
foreach ($pages->find('template=event') as $event) {
    $eventTime = new \DateTime($event->event_date, new \DateTimeZone('UTC'));

    if ($user->timezone) {
        $userTz = new \DateTimeZone($user->timezone);
        $eventTime->setTimezone($userTz);
    }

    echo "<div>";
    echo "<h3>" . $event->title . "</h3>";
    echo "<time>" . $eventTime->format('l, F j, Y - g:i A T') . "</time>";
    echo "</div>";
    // Outputs: Tuesday, December 31, 2025 - 5:13 PM EST
}

Example 3: Auto-detect Timezone (with JavaScript)

// In registration form template
<script>
// Automatically detect browser timezone
document.addEventListener('DOMContentLoaded', function() {
    const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
    const field = document.getElementById('timezone_field');

    if (field && timezone) {
        field.value = timezone;
    }
});
</script>

<select id="timezone_field" name="user_timezone">
    <!-- Options will be populated by ProcessWire -->
</select>

Security


Data Validation

  • Automatic sanitization of all input data
  • Validation of timezone identifiers
  • Protection against SQL injection via parameterized queries
  • Database field indexing for optimization

Error Handling

// Safe handling of invalid timezones
try {
    $tz = new \DateTimeZone($page->user_timezone);
} catch (Exception $e) {
    // Fallback to UTC
    $tz = new \DateTimeZone('UTC');
    $this->log->save('timezone-errors',
        "Invalid timezone: {$page->user_timezone}");
}

⚡ Performance


Caching

The module automatically caches the timezone list for 24 hours:

// Manually clear cache (if needed)
$cache = wire('cache');
$cache->deleteFor('InputfieldTimezone_*');

Database Optimization

The field is automatically indexed for fast lookup:

KEY data (data)

️ Extending Functionality


Adding New Timezones

If you need to add additional timezones:

// In InputfieldTimezone.module.php, extend the $timezoneMapping array
protected static $timezoneMapping = [
    'Your/Custom_Timezone' => ['Your Country', 'Your City'],
    // ...
];

Changelog


Version 1.0.0 (2025-10-03)

Stable Release

Added:

  • Dynamic UTC offset calculation with DST support
  • Intelligent caching (24 hours)
  • Database field indexing
  • getTimezoneInfo() API method
  • Extended data validation
  • Simple and reliable functionality without complex settings

Changed:

  • Complete module architecture rewrite
  • Performance optimization
  • Improved code structure
  • Updated documentation

Fixed:

  • Removed duplicate timezone entries
  • Fixed encoding issues
  • Improved error handling

Version 0.1.0 (Beta)

  • Initial release

Support and Contribution


Report an Issue

License


This module is distributed under the Mozilla Public License 2.0.

More modules by Maxim Semenov

  • LQRS URL Shortener Profile for ProcessWire 3x

    This site profile for ProcessWire offers a free and easy-to-use URL shortener that transforms long links into concise, shareable URLs. It is built using standard ProcessWire modules and field types.
  • WireWall

    Advanced traffic firewall with VPN/Proxy/Tor detection, rate limiting, and JS challenge
  • Media Platform Profile for ProcessWire

    This site profile for ProcessWire offers a fully-featured media platform for hosting and managing video content with Backblaze B2 and Cloudflare integration.
  • AgeWire

    Age verification module with Tailwind CSS support
  • 2048

    Take a break with 2048 game in ProcessWire admin
  • WireNPS - Net Promoter Score

    Collect NPS ratings and feedback with a clean popup interface, comprehensive analytics, and easy integration
  • Timezone

    Fieldtype for storing timezone values with dynamic UTC offsets.
  • Embedr

    Manage dynamic content embeds with live preview
  • Square Images

    Creates perfect square images from any source format with smart cropping

All modules by Maxim Semenov

Install and use modules at your own risk. Always have a site and database backup before installing new modules.