feat: Add timezone support with EST default

- Add TIMEZONE config option (default: America/New_York)
- Set PHP default timezone from config
- Add timezone offset and abbreviation for JavaScript
- Update stat card filters to use server timezone
- Add timezone config to Dashboard and Ticket views

Timezone can be changed via TIMEZONE env variable.
All dates now consistent with server timezone (EST by default).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-20 21:48:25 -05:00
parent 2c35ccc199
commit 8b4ef2a7f5
3 changed files with 36 additions and 2 deletions

View File

@@ -65,6 +65,20 @@ $GLOBALS['config'] = [
'RATE_LIMIT_API' => 60, // Requests per minute for API 'RATE_LIMIT_API' => 60, // Requests per minute for API
// Audit log settings // Audit log settings
'AUDIT_LOG_RETENTION_DAYS' => 90 'AUDIT_LOG_RETENTION_DAYS' => 90,
// Timezone settings
// Default: America/New_York (EST/EDT)
// Common options: America/Chicago (CST), America/Denver (MST), America/Los_Angeles (PST), UTC
'TIMEZONE' => $envVars['TIMEZONE'] ?? 'America/New_York',
'TIMEZONE_OFFSET' => null // Will be calculated below
]; ];
// Set PHP default timezone
date_default_timezone_set($GLOBALS['config']['TIMEZONE']);
// Calculate UTC offset for JavaScript (in minutes, negative for west of UTC)
$now = new DateTime('now', new DateTimeZone($GLOBALS['config']['TIMEZONE']));
$GLOBALS['config']['TIMEZONE_OFFSET'] = $now->getOffset() / 60; // Convert seconds to minutes
$GLOBALS['config']['TIMEZONE_ABBREV'] = $now->format('T'); // e.g., "EST", "EDT"
?> ?>

View File

@@ -20,6 +20,10 @@
require_once __DIR__ . '/../middleware/CsrfMiddleware.php'; require_once __DIR__ . '/../middleware/CsrfMiddleware.php';
echo CsrfMiddleware::getToken(); echo CsrfMiddleware::getToken();
?>'; ?>';
// Timezone configuration (from server)
window.APP_TIMEZONE = '<?php echo $GLOBALS['config']['TIMEZONE']; ?>';
window.APP_TIMEZONE_OFFSET = <?php echo $GLOBALS['config']['TIMEZONE_OFFSET']; ?>; // minutes from UTC
window.APP_TIMEZONE_ABBREV = '<?php echo $GLOBALS['config']['TIMEZONE_ABBREV']; ?>';
</script> </script>
</head> </head>
<body data-categories='<?php echo json_encode($categories); ?>' data-types='<?php echo json_encode($types); ?>'> <body data-categories='<?php echo json_encode($categories); ?>' data-types='<?php echo json_encode($types); ?>'>
@@ -693,13 +697,25 @@
} }
}); });
// Helper function to get date in server timezone
function getServerDate() {
// Get current UTC time
const now = new Date();
// Apply server timezone offset (APP_TIMEZONE_OFFSET is in minutes)
const serverTime = new Date(now.getTime() + (window.APP_TIMEZONE_OFFSET * 60000) + (now.getTimezoneOffset() * 60000));
return serverTime.getFullYear() + '-' +
String(serverTime.getMonth() + 1).padStart(2, '0') + '-' +
String(serverTime.getDate()).padStart(2, '0');
}
// Stat card click handlers for filtering // Stat card click handlers for filtering
document.querySelectorAll('.stat-card').forEach(card => { document.querySelectorAll('.stat-card').forEach(card => {
card.style.cursor = 'pointer'; card.style.cursor = 'pointer';
card.addEventListener('click', function() { card.addEventListener('click', function() {
const classList = this.classList; const classList = this.classList;
let url = '/?'; let url = '/?';
const today = new Date().toISOString().split('T')[0]; // Use server timezone date (default: EST)
const today = getServerDate();
if (classList.contains('stat-open')) { if (classList.contains('stat-open')) {
url += 'status=Open'; url += 'status=Open';

View File

@@ -58,6 +58,10 @@ function formatDetails($details, $actionType) {
require_once __DIR__ . '/../middleware/CsrfMiddleware.php'; require_once __DIR__ . '/../middleware/CsrfMiddleware.php';
echo CsrfMiddleware::getToken(); echo CsrfMiddleware::getToken();
?>'; ?>';
// Timezone configuration (from server)
window.APP_TIMEZONE = '<?php echo $GLOBALS['config']['TIMEZONE']; ?>';
window.APP_TIMEZONE_OFFSET = <?php echo $GLOBALS['config']['TIMEZONE_OFFSET']; ?>; // minutes from UTC
window.APP_TIMEZONE_ABBREV = '<?php echo $GLOBALS['config']['TIMEZONE_ABBREV']; ?>';
</script> </script>
<script> <script>
// Store ticket data in a global variable // Store ticket data in a global variable