| ← Back to Timezone Handling | Back to JavaScript Development |
Timezone Input Controller
Location: app/assets/js/controllers/timezone-input-controller.js
Framework: Stimulus.js
Dependencies: KMP_Timezone utility
Related: KMP_Timezone API Reference
Overview
The Timezone Input Controller automatically handles timezone conversion for datetime-local HTML form inputs. It simplifies the workflow of converting UTC values from the server to the user’s local timezone for display and editing, then converting back to UTC before form submission.
Key responsibility: Bridge between server-side UTC storage and client-side user timezone display/input.
Features
- Automatic Timezone Detection: Detects user’s browser timezone using
Intl.DateTimeFormatAPI - UTC to Local Conversion: Converts server UTC values to local time for input fields on page load
- Local to UTC Conversion: Converts user input from local time back to UTC before submission
- Timezone Notice: Displays the current timezone to the user (optional)
- Multiple Input Support: Handles multiple datetime inputs in a single form
- Form Reset Support: Restores original local values when form is reset
- Configurable Timezone: Allows override of detected timezone via data attributes
Installation & Setup
Controller Registration
The controller is automatically registered in app/assets/js/index.js:
// All Stimulus controllers are registered automatically
for (var controller in window.Controllers) {
Stimulus.register(controller, window.Controllers[controller]);
}
No Additional Setup Required
Simply use the controller in your HTML forms with the appropriate data attributes.
Basic Usage
Simplest Example
<form data-controller="timezone-input">
<div class="mb-3">
<label for="start_date" class="form-label">Start Date/Time</label>
<input type="datetime-local"
id="start_date"
name="start_date"
data-timezone-input-target="datetimeInput"
data-utc-value="2025-03-15T14:30:00Z"
class="form-control">
</div>
<button type="submit" class="btn btn-primary">Save</button>
</form>
What happens:
- On page load: UTC value
2025-03-15T14:30:00Zis converted to user’s local time (e.g.,2025-03-15T09:30for Chicago) - User edits the time locally
- On form submit: Local time is converted back to UTC for storage
With Timezone Notice
Show the user which timezone is being used:
<form data-controller="timezone-input">
<div class="mb-3">
<label for="start_date" class="form-label">Start Date/Time</label>
<input type="datetime-local"
id="start_date"
name="start_date"
data-timezone-input-target="datetimeInput"
data-utc-value="2025-03-15T14:30:00Z"
class="form-control">
<small data-timezone-input-target="notice" class="text-muted d-block mt-2"></small>
</div>
</form>
Output: <i class="bi bi-clock"></i> Times shown in America/Chicago (CDT)
With Custom Timezone
Override the detected timezone:
<form data-controller="timezone-input"
data-timezone-input-timezone-value="America/New_York">
<input type="datetime-local"
name="start_date"
data-timezone-input-target="datetimeInput"
data-utc-value="2025-03-15T14:30:00Z"
class="form-control">
</form>
Use cases:
- Event scheduled in a specific timezone (use gathering’s timezone)
- Server managing times for a different region
- User preference override
Disabling Timezone Notice
<form data-controller="timezone-input"
data-timezone-input-show-notice-value="false">
<input type="datetime-local"
name="start_date"
data-timezone-input-target="datetimeInput"
data-utc-value="2025-03-15T14:30:00Z"
class="form-control">
</form>
Stimulus Targets
datetimeInput (required)
The datetime-local input elements to convert.
Attributes required:
data-timezone-input-target="datetimeInput"- Identifies the input for the controllerdata-utc-value="..."- The UTC datetime value from the server
Example:
<input type="datetime-local"
name="event_start"
data-timezone-input-target="datetimeInput"
data-utc-value="2025-03-15T14:30:00Z">
notice (optional)
Elements to display timezone information to the user.
Features:
- Automatically populated with timezone name and abbreviation
- Shows timezone icon (uses Bootstrap Icons
bi-clockclass) - Empty by default until controller connects
Example:
<small data-timezone-input-target="notice" class="text-muted"></small>
Auto-populated content:
<i class="bi bi-clock"></i> Times shown in America/Chicago (CDT)
Stimulus Values
timezone (optional)
Override the detected timezone with a specific IANA timezone identifier.
Type: String
Default: Browser-detected timezone
Example: America/Chicago, America/New_York, UTC
Usage:
<form data-controller="timezone-input"
data-timezone-input-timezone-value="America/New_York">
showNotice (optional)
Control whether timezone notice elements are populated.
Type: Boolean
Default: true
Values: true or false
Usage:
<!-- Show notice (default) -->
<form data-controller="timezone-input"
data-timezone-input-show-notice-value="true">
<!-- Hide notice -->
<form data-controller="timezone-input"
data-timezone-input-show-notice-value="false">
Lifecycle Methods
connect() - Controller Initialization
Called when the form element connects to the DOM.
What it does:
- Detects or retrieves configured timezone
- Converts all UTC input values to local time
- Populates timezone notice if enabled
- Sets up submit and reset event listeners
Key features:
- Binds event handlers with proper cleanup references
- Attaches listeners for form submit and reset events
- Initializes notice elements with current timezone info
convertUtcToLocal() - Convert on Page Load
Processes all datetime inputs and converts UTC values to local time.
What it does:
- Finds all inputs with
data-utc-valueattribute - Converts each UTC value to local time for the configured timezone
- Sets input value to the converted local time
- Stores original and converted values in data attributes for reference
Data attributes set:
data-original-utc- The original UTC value (for reference)data-local-value- The converted local value (for reset)
updateNotice() - Display Timezone Info
Updates all notice target elements with current timezone information.
Output format:
<i class="bi bi-clock"></i> Times shown in {TIMEZONE} ({ABBR})
Example:
<i class="bi bi-clock"></i> Times shown in America/Chicago (CDT)
handleSubmit() - Convert Before Submission
Called on form submission to convert local times back to UTC.
What it does:
- Iterates through all datetime inputs
- Converts local time to UTC for each input
- Creates hidden input fields with UTC values
- Disables original inputs to prevent duplicate submission
- Appends hidden inputs to form
Result: Server receives UTC values in hidden inputs
handleReset() - Restore on Form Reset
Called when form is reset (via reset button or JavaScript).
What it does:
- Removes any hidden UTC input fields created during submission
- Re-enables original datetime inputs
- Restores local time values from stored data
- Uses
setTimeoutto ensure DOM is ready before restoring values
Public Methods
updateTimezone(newTimezone)
Manually update the timezone being used for conversion.
Parameters:
newTimezone(string): New IANA timezone identifier
What it does:
- Updates controller’s timezone setting
- Re-converts all input values with the new timezone
- Updates notice if enabled
Example:
// Get controller instance
const form = document.querySelector('[data-controller="timezone-input"]');
const controller = form._stimulus_module.element;
// Update to different timezone
controller.updateTimezone('America/New_York');
getTimezone()
Get the current timezone being used.
Returns: IANA timezone identifier string
Example:
const timezone = controller.getTimezone();
console.log(timezone); // "America/Chicago"
disconnect() - Cleanup
Called when the controller disconnects from the DOM.
What it does:
- Removes submit event listener
- Removes reset event listener
- Clears cached event handler references
- Prevents memory leaks
Complete Example
Multi-Field Form with Timezone Control
<form id="eventForm" data-controller="timezone-input">
<fieldset>
<legend>Event Details</legend>
<!-- Event Start Time -->
<div class="mb-3">
<label for="start_date" class="form-label">Event Start</label>
<input type="datetime-local"
id="start_date"
name="start_date"
data-timezone-input-target="datetimeInput"
data-utc-value="2025-03-15T14:30:00Z"
class="form-control"
required>
</div>
<!-- Event End Time -->
<div class="mb-3">
<label for="end_date" class="form-label">Event End</label>
<input type="datetime-local"
id="end_date"
name="end_date"
data-timezone-input-target="datetimeInput"
data-utc-value="2025-03-15T16:30:00Z"
class="form-control"
required>
</div>
<!-- Timezone Notice -->
<div class="alert alert-info" role="alert">
<small data-timezone-input-target="notice"></small>
</div>
</fieldset>
<div class="button-group">
<button type="submit" class="btn btn-primary">Save Event</button>
<button type="reset" class="btn btn-secondary">Clear</button>
</div>
</form>
Behavior:
- Both datetime inputs display in user’s local timezone
- User edits times as needed
- Notice shows current timezone
- On submit: Both values sent as UTC to server
- On reset: Both values restored to original local times
Form Data Flow
Submission Flow
User Input (Local Time)
↓
datetime-local input contains: 2025-03-15T09:30
↓
Form submission triggered
↓
handleSubmit() converts to UTC
↓
Hidden inputs created: 2025-03-15T14:30:00.000Z
↓
Original inputs disabled
↓
Hidden inputs included in form data
↓
Server receives: name_of_input=2025-03-15T14:30:00.000Z
Reset Flow
Form reset triggered
↓
handleReset() removes hidden inputs
↓
Original datetime inputs re-enabled
↓
Values restored from data-local-value
↓
Form state returns to pre-submission local times
Integration with KMP_Timezone
The controller uses the global KMP_Timezone utility for all timezone operations:
Methods used:
KMP_Timezone.detectTimezone()- Detect user’s timezone on connectKMP_Timezone.toLocalInput()- Convert UTC to local for input displayKMP_Timezone.toUTC()- Convert local input to UTC for submissionKMP_Timezone.getAbbreviation()- Get timezone abbreviation for notice
See: KMP_Timezone API Reference for complete API documentation.
Common Patterns
Pattern 1: Simple Date/Time Input
<form data-controller="timezone-input">
<input type="datetime-local"
name="appointment"
data-timezone-input-target="datetimeInput"
data-utc-value="2025-03-15T14:00:00Z">
</form>
Pattern 2: Event with Location Timezone
<form data-controller="timezone-input"
data-timezone-input-timezone-value="<?= h($event->timezone) ?>">
<input type="datetime-local"
name="start_time"
data-timezone-input-target="datetimeInput"
data-utc-value="<?= h($event->start_time->toIso8601String()) ?>">
<small data-timezone-input-target="notice" class="text-muted"></small>
</form>
Pattern 3: Date Range
<form data-controller="timezone-input">
<div class="row">
<div class="col-md-6">
<label>From:</label>
<input type="datetime-local"
name="date_from"
data-timezone-input-target="datetimeInput"
data-utc-value="2025-03-15T00:00:00Z">
</div>
<div class="col-md-6">
<label>To:</label>
<input type="datetime-local"
name="date_to"
data-timezone-input-target="datetimeInput"
data-utc-value="2025-03-15T23:59:59Z">
</div>
</div>
<small data-timezone-input-target="notice" class="text-muted d-block mt-2"></small>
</form>
Troubleshooting
Issue: Times showing as UTC instead of local timezone
Cause: Controller not initialized or data-controller="timezone-input" missing
Solution:
- Verify
data-controller="timezone-input"is on the form element - Check browser console for JavaScript errors
- Ensure
KMP_Timezoneutility is loaded
Issue: Timezone notice not appearing
Cause: Missing or incorrect notice target
Solution:
- Add
data-timezone-input-target="notice"to notice element - Ensure element has correct CSS class for visibility
- Check if
showNoticevalue is set tofalse
Issue: Form not converting times to UTC on submit
Cause: Missing or incorrect datetime input targets
Solution:
- Verify all inputs have
data-timezone-input-target="datetimeInput" - Check that inputs are of type
datetime-local - Ensure form has
data-controller="timezone-input"
Issue: Custom timezone not being used
Cause: Invalid timezone identifier or typo in data attribute
Solution:
- Verify timezone is a valid IANA identifier
- Use
KMP_Timezone.detectTimezone()to test timezone detection - Check browser console for error messages
Performance Considerations
- Lazy Conversion: Times are only converted when necessary (page load, submit, reset)
- Event Delegation: Uses form-level submit and reset handlers instead of per-input listeners
- Memory Management: Properly cleans up event listeners on disconnect to prevent memory leaks
Browser Compatibility
The controller relies on:
- Intl.DateTimeFormat API: Supported in all modern browsers
- HTML5 datetime-local input type: Supported in Chrome 25+, Firefox 93+, Safari 14.1+, Edge 79+
Fallback: For older browsers, the input will display as text, but timezone conversion will still work.
See Also
- Timezone Handling Guide - Complete timezone system documentation
- KMP_Timezone API Reference - Timezone utility methods
- Stimulus Documentation - Stimulus framework reference
- MDN: datetime-local input - HTML5 datetime-local specification
| ← Back to Timezone Handling | Back to JavaScript Development |