Add timezone-aware date filtering for reports page

- Add parse_timezone_offset() helper to parse timezone strings (UTC+3, Africa/Johannesburg, etc.)
- Add get_date_range_in_timezone() helper to calculate date ranges with proper timezone conversion
- Update reports(), export_reports(), client_report_detail(), match_report_detail(), export_client_report(), and export_match_report() to use timezone-aware date filtering
- Users can now select their timezone and date filters will correctly convert local time boundaries to UTC for database queries
parent ff2344d2
import logging import logging
import os import os
from datetime import datetime, timedelta from datetime import datetime, timedelta, timezone
from flask import render_template, request, jsonify, redirect, url_for, flash, current_app from flask import render_template, request, jsonify, redirect, url_for, flash, current_app
from flask_login import login_required, current_user from flask_login import login_required, current_user
from app.main import bp from app.main import bp
...@@ -14,6 +14,197 @@ from flask import Response, make_response ...@@ -14,6 +14,197 @@ from flask import Response, make_response
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def parse_timezone_offset(tz_string):
"""
Parse a timezone string and return a timezone object.
Supports both named timezones (e.g., 'Africa/Johannesburg') and UTC offsets (e.g., 'UTC+3', 'UTC-5', 'UTC+5:30').
Args:
tz_string: Timezone string (e.g., 'UTC+3', 'Africa/Johannesburg', 'auto')
Returns:
A timezone object or None for 'auto' (should use browser timezone)
"""
if not tz_string or tz_string == 'auto':
return None
if tz_string == 'UTC' or tz_string == 'UTC+0':
return timezone.utc
# Check if it's a UTC offset format (e.g., 'UTC+3', 'UTC-5', 'UTC+5:30')
if tz_string.startswith('UTC'):
offset_str = tz_string[3:] # Remove 'UTC' prefix
if not offset_str:
return timezone.utc
# Parse the offset
try:
# Handle formats like '+3', '-5', '+5:30', '-9:30'
if ':' in offset_str:
# Handle hours:minutes format
sign = 1 if offset_str[0] == '+' else -1
parts = offset_str[1:].split(':')
hours = int(parts[0])
minutes = int(parts[1]) if len(parts) > 1 else 0
total_minutes = sign * (hours * 60 + minutes)
else:
# Handle simple hour format
sign = 1 if offset_str[0] == '+' else -1
hours = int(offset_str[1:])
total_minutes = sign * hours * 60
# Create a fixed offset timezone
return timezone(timedelta(minutes=total_minutes))
except (ValueError, IndexError):
logger.warning(f"Invalid UTC offset format: {tz_string}, defaulting to UTC")
return timezone.utc
# Try to parse as a named timezone (e.g., 'Africa/Johannesburg')
try:
from zoneinfo import ZoneInfo
return ZoneInfo(tz_string)
except (ImportError, Exception) as e:
# Fallback for Python < 3.9 or invalid timezone names
logger.warning(f"Could not parse timezone '{tz_string}': {e}, defaulting to UTC")
return timezone.utc
def get_date_range_in_timezone(date_range_filter, start_date_filter, end_date_filter,
start_time_filter, end_time_filter, tz_string):
"""
Calculate date range boundaries in the user's timezone and convert to UTC for database queries.
Args:
date_range_filter: Date range type ('today', 'yesterday', 'this_week', 'last_week',
'this_month', 'all', 'custom')
start_date_filter: Custom start date string (YYYY-MM-DD format)
end_date_filter: Custom end date string (YYYY-MM-DD format)
start_time_filter: Custom start time string (HH:MM format)
end_time_filter: Custom end time string (HH:MM format)
tz_string: Timezone string (e.g., 'UTC+3', 'Africa/Johannesburg')
Returns:
Tuple of (start_date_utc, end_date_utc) as naive datetime objects for database queries
"""
# Parse the timezone
tz = parse_timezone_offset(tz_string)
# If no timezone specified or 'auto', use UTC (server default)
if tz is None:
tz = timezone.utc
# Get current time in the user's timezone
now_utc = datetime.now(timezone.utc)
now_local = now_utc.astimezone(tz)
start_date = None
end_date = None
if date_range_filter == 'today':
# Start of today in user's local timezone
start_local = now_local.replace(hour=0, minute=0, second=0, microsecond=0)
end_local = now_local
# Convert to UTC
start_date = start_local.astimezone(timezone.utc).replace(tzinfo=None)
end_date = end_local.astimezone(timezone.utc).replace(tzinfo=None)
elif date_range_filter == 'yesterday':
# Start of yesterday in user's local timezone
yesterday_local = now_local - timedelta(days=1)
start_local = yesterday_local.replace(hour=0, minute=0, second=0, microsecond=0)
end_local = yesterday_local.replace(hour=23, minute=59, second=59, microsecond=999999)
# Convert to UTC
start_date = start_local.astimezone(timezone.utc).replace(tzinfo=None)
end_date = end_local.astimezone(timezone.utc).replace(tzinfo=None)
elif date_range_filter == 'this_week':
# Start of current week (Monday) in user's local timezone
days_since_monday = now_local.weekday()
start_local = now_local - timedelta(days=days_since_monday)
start_local = start_local.replace(hour=0, minute=0, second=0, microsecond=0)
end_local = now_local
# Convert to UTC
start_date = start_local.astimezone(timezone.utc).replace(tzinfo=None)
end_date = end_local.astimezone(timezone.utc).replace(tzinfo=None)
elif date_range_filter == 'last_week':
# Start of last week (Monday) in user's local timezone
days_since_monday = now_local.weekday()
last_week_end_local = now_local - timedelta(days=days_since_monday + 1)
last_week_start_local = last_week_end_local - timedelta(days=6)
start_local = last_week_start_local.replace(hour=0, minute=0, second=0, microsecond=0)
end_local = last_week_end_local.replace(hour=23, minute=59, second=59, microsecond=999999)
# Convert to UTC
start_date = start_local.astimezone(timezone.utc).replace(tzinfo=None)
end_date = end_local.astimezone(timezone.utc).replace(tzinfo=None)
elif date_range_filter == 'this_month':
# Start of current month in user's local timezone
start_local = now_local.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
end_local = now_local
# Convert to UTC
start_date = start_local.astimezone(timezone.utc).replace(tzinfo=None)
end_date = end_local.astimezone(timezone.utc).replace(tzinfo=None)
elif date_range_filter == 'all':
start_date = None
end_date = None
elif date_range_filter == 'custom':
# Parse custom date range
if start_date_filter:
try:
# Parse the date string
start_date_parsed = datetime.strptime(start_date_filter, '%Y-%m-%d')
# Apply time if provided
if start_time_filter:
try:
hour, minute = map(int, start_time_filter.split(':'))
start_date_parsed = start_date_parsed.replace(hour=hour, minute=minute, second=0, microsecond=0)
except (ValueError, AttributeError):
start_date_parsed = start_date_parsed.replace(hour=0, minute=0, second=0, microsecond=0)
else:
start_date_parsed = start_date_parsed.replace(hour=0, minute=0, second=0, microsecond=0)
# Treat the parsed date as being in the user's timezone
start_date_local = start_date_parsed.replace(tzinfo=tz)
start_date = start_date_local.astimezone(timezone.utc).replace(tzinfo=None)
except ValueError:
pass
if end_date_filter:
try:
# Parse the date string
end_date_parsed = datetime.strptime(end_date_filter, '%Y-%m-%d')
# Apply time if provided
if end_time_filter:
try:
hour, minute = map(int, end_time_filter.split(':'))
end_date_parsed = end_date_parsed.replace(hour=hour, minute=minute, second=59, microsecond=999999)
except (ValueError, AttributeError):
end_date_parsed = end_date_parsed.replace(hour=23, minute=59, second=59, microsecond=999999)
else:
end_date_parsed = end_date_parsed.replace(hour=23, minute=59, second=59, microsecond=999999)
# Treat the parsed date as being in the user's timezone
end_date_local = end_date_parsed.replace(tzinfo=tz)
end_date = end_date_local.astimezone(timezone.utc).replace(tzinfo=None)
except ValueError:
pass
return start_date, end_date
@csrf.exempt @csrf.exempt
@bp.route('/') @bp.route('/')
def index(): def index():
...@@ -1560,57 +1751,11 @@ def reports(): ...@@ -1560,57 +1751,11 @@ def reports():
page = request.args.get('page', 1, type=int) page = request.args.get('page', 1, type=int)
per_page = min(request.args.get('per_page', 50, type=int), 100) per_page = min(request.args.get('per_page', 50, type=int), 100)
# Calculate date range based on filter # Calculate date range based on filter with timezone conversion
now = datetime.utcnow() start_date, end_date = get_date_range_in_timezone(
start_date = None date_range_filter, start_date_filter, end_date_filter,
end_date = None start_time_filter, end_time_filter, timezone_filter
)
if date_range_filter == 'today':
start_date = now.replace(hour=0, minute=0, second=0, microsecond=0)
end_date = now
elif date_range_filter == 'yesterday':
yesterday = now - timedelta(days=1)
start_date = yesterday.replace(hour=0, minute=0, second=0, microsecond=0)
end_date = yesterday.replace(hour=23, minute=59, second=59, microsecond=999999)
elif date_range_filter == 'this_week':
# Start of current week (Monday)
start_date = now - timedelta(days=now.weekday())
start_date = start_date.replace(hour=0, minute=0, second=0, microsecond=0)
end_date = now
elif date_range_filter == 'last_week':
# Start of last week (Monday)
last_week_end = now - timedelta(days=now.weekday() + 1)
last_week_start = last_week_end - timedelta(days=6)
start_date = last_week_start.replace(hour=0, minute=0, second=0, microsecond=0)
end_date = last_week_end.replace(hour=23, minute=59, second=59, microsecond=999999)
elif date_range_filter == 'this_month':
start_date = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
end_date = now
elif date_range_filter == 'all':
start_date = None
end_date = None
elif date_range_filter == 'custom':
# Use custom date range
if start_date_filter:
try:
start_date = datetime.strptime(start_date_filter, '%Y-%m-%d')
if start_time_filter:
hour, minute = map(int, start_time_filter.split(':'))
start_date = start_date.replace(hour=hour, minute=minute, second=0, microsecond=0)
else:
start_date = start_date.replace(hour=0, minute=0, second=0, microsecond=0)
except ValueError:
pass
if end_date_filter:
try:
end_date = datetime.strptime(end_date_filter, '%Y-%m-%d')
if end_time_filter:
hour, minute = map(int, end_time_filter.split(':'))
end_date = end_date.replace(hour=hour, minute=minute, second=59, microsecond=999999)
else:
end_date = end_date.replace(hour=23, minute=59, second=59, microsecond=999999)
except ValueError:
pass
# Base query # Base query
if current_user.is_admin: if current_user.is_admin:
...@@ -1922,54 +2067,11 @@ def export_reports(query, export_format): ...@@ -1922,54 +2067,11 @@ def export_reports(query, export_format):
end_time_filter = request.args.get('end_time', '').strip() end_time_filter = request.args.get('end_time', '').strip()
timezone_filter = request.args.get('timezone', 'auto').strip() timezone_filter = request.args.get('timezone', 'auto').strip()
# Calculate date range based on filter # Calculate date range based on filter with timezone conversion
now = datetime.utcnow() start_date, end_date = get_date_range_in_timezone(
start_date = None date_range_filter, start_date_filter, end_date_filter,
end_date = None start_time_filter, end_time_filter, timezone_filter
)
if date_range_filter == 'today':
start_date = now.replace(hour=0, minute=0, second=0, microsecond=0)
end_date = now
elif date_range_filter == 'yesterday':
yesterday = now - timedelta(days=1)
start_date = yesterday.replace(hour=0, minute=0, second=0, microsecond=0)
end_date = yesterday.replace(hour=23, minute=59, second=59, microsecond=999999)
elif date_range_filter == 'this_week':
start_date = now - timedelta(days=now.weekday())
start_date = start_date.replace(hour=0, minute=0, second=0, microsecond=0)
end_date = now
elif date_range_filter == 'last_week':
last_week_end = now - timedelta(days=now.weekday() + 1)
last_week_start = last_week_end - timedelta(days=6)
start_date = last_week_start.replace(hour=0, minute=0, second=0, microsecond=0)
end_date = last_week_end.replace(hour=23, minute=59, second=59, microsecond=999999)
elif date_range_filter == 'this_month':
start_date = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
end_date = now
elif date_range_filter == 'all':
start_date = None
end_date = None
elif date_range_filter == 'custom':
if start_date_filter:
try:
start_date = datetime.strptime(start_date_filter, '%Y-%m-%d')
if start_time_filter:
hour, minute = map(int, start_time_filter.split(':'))
start_date = start_date.replace(hour=hour, minute=minute, second=0, microsecond=0)
else:
start_date = start_date.replace(hour=0, minute=0, second=0, microsecond=0)
except ValueError:
pass
if end_date_filter:
try:
end_date = datetime.strptime(end_date_filter, '%Y-%m-%d')
if end_time_filter:
hour, minute = map(int, end_time_filter.split(':'))
end_date = end_date.replace(hour=hour, minute=minute, second=59, microsecond=999999)
else:
end_date = end_date.replace(hour=23, minute=59, second=59, microsecond=999999)
except ValueError:
pass
# Build query for MatchReport data (same as reports page) # Build query for MatchReport data (same as reports page)
base_query = MatchReport.query base_query = MatchReport.query
...@@ -2418,54 +2520,11 @@ def export_match_report(client_id, match_id, export_format): ...@@ -2418,54 +2520,11 @@ def export_match_report(client_id, match_id, export_format):
end_time_filter = request.args.get('end_time', '').strip() end_time_filter = request.args.get('end_time', '').strip()
timezone_filter = request.args.get('timezone', 'auto').strip() timezone_filter = request.args.get('timezone', 'auto').strip()
# Calculate date range # Calculate date range based on filter with timezone conversion
now = datetime.utcnow() start_date, end_date = get_date_range_in_timezone(
start_date = None date_range_filter, start_date_filter, end_date_filter,
end_date = None start_time_filter, end_time_filter, timezone_filter
)
if date_range_filter == 'today':
start_date = now.replace(hour=0, minute=0, second=0, microsecond=0)
end_date = now
elif date_range_filter == 'yesterday':
yesterday = now - timedelta(days=1)
start_date = yesterday.replace(hour=0, minute=0, second=0, microsecond=0)
end_date = yesterday.replace(hour=23, minute=59, second=59, microsecond=999999)
elif date_range_filter == 'this_week':
start_date = now - timedelta(days=now.weekday())
start_date = start_date.replace(hour=0, minute=0, second=0, microsecond=0)
end_date = now
elif date_range_filter == 'last_week':
last_week_end = now - timedelta(days=now.weekday() + 1)
last_week_start = last_week_end - timedelta(days=6)
start_date = last_week_start.replace(hour=0, minute=0, second=0, microsecond=0)
end_date = last_week_end.replace(hour=23, minute=59, second=59, microsecond=999999)
elif date_range_filter == 'this_month':
start_date = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
end_date = now
elif date_range_filter == 'all':
start_date = None
end_date = None
elif date_range_filter == 'custom':
if start_date_filter:
try:
start_date = datetime.strptime(start_date_filter, '%Y-%m-%d')
if start_time_filter:
hour, minute = map(int, start_time_filter.split(':'))
start_date = start_date.replace(hour=hour, minute=minute, second=0, microsecond=0)
else:
start_date = start_date.replace(hour=0, minute=0, second=0, microsecond=0)
except ValueError:
pass
if end_date_filter:
try:
end_date = datetime.strptime(end_date_filter, '%Y-%m-%d')
if end_time_filter:
hour, minute = map(int, end_time_filter.split(':'))
end_date = end_date.replace(hour=hour, minute=minute, second=59, microsecond=999999)
else:
end_date = end_date.replace(hour=23, minute=59, second=59, microsecond=999999)
except ValueError:
pass
# Check if user has access to this client # Check if user has access to this client
if current_user.is_admin: if current_user.is_admin:
...@@ -2649,54 +2708,11 @@ def export_client_report(client_id, export_format): ...@@ -2649,54 +2708,11 @@ def export_client_report(client_id, export_format):
end_time_filter = request.args.get('end_time', '').strip() end_time_filter = request.args.get('end_time', '').strip()
timezone_filter = request.args.get('timezone', 'auto').strip() timezone_filter = request.args.get('timezone', 'auto').strip()
# Calculate date range # Calculate date range based on filter with timezone conversion
now = datetime.utcnow() start_date, end_date = get_date_range_in_timezone(
start_date = None date_range_filter, start_date_filter, end_date_filter,
end_date = None start_time_filter, end_time_filter, timezone_filter
)
if date_range_filter == 'today':
start_date = now.replace(hour=0, minute=0, second=0, microsecond=0)
end_date = now
elif date_range_filter == 'yesterday':
yesterday = now - timedelta(days=1)
start_date = yesterday.replace(hour=0, minute=0, second=0, microsecond=0)
end_date = yesterday.replace(hour=23, minute=59, second=59, microsecond=999999)
elif date_range_filter == 'this_week':
start_date = now - timedelta(days=now.weekday())
start_date = start_date.replace(hour=0, minute=0, second=0, microsecond=0)
end_date = now
elif date_range_filter == 'last_week':
last_week_end = now - timedelta(days=now.weekday() + 1)
last_week_start = last_week_end - timedelta(days=6)
start_date = last_week_start.replace(hour=0, minute=0, second=0, microsecond=0)
end_date = last_week_end.replace(hour=23, minute=59, second=59, microsecond=999999)
elif date_range_filter == 'this_month':
start_date = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
end_date = now
elif date_range_filter == 'all':
start_date = None
end_date = None
elif date_range_filter == 'custom':
if start_date_filter:
try:
start_date = datetime.strptime(start_date_filter, '%Y-%m-%d')
if start_time_filter:
hour, minute = map(int, start_time_filter.split(':'))
start_date = start_date.replace(hour=hour, minute=minute, second=0, microsecond=0)
else:
start_date = start_date.replace(hour=0, minute=0, second=0, microsecond=0)
except ValueError:
pass
if end_date_filter:
try:
end_date = datetime.strptime(end_date_filter, '%Y-%m-%d')
if end_time_filter:
hour, minute = map(int, end_time_filter.split(':'))
end_date = end_date.replace(hour=hour, minute=minute, second=59, microsecond=999999)
else:
end_date = end_date.replace(hour=23, minute=59, second=59, microsecond=999999)
except ValueError:
pass
# Check if user has access to this client # Check if user has access to this client
if current_user.is_admin: if current_user.is_admin:
...@@ -3099,54 +3115,11 @@ def client_report_detail(client_id): ...@@ -3099,54 +3115,11 @@ def client_report_detail(client_id):
page = request.args.get('page', 1, type=int) page = request.args.get('page', 1, type=int)
per_page = min(request.args.get('per_page', 50, type=int), 100) per_page = min(request.args.get('per_page', 50, type=int), 100)
# Calculate date range # Calculate date range based on filter with timezone conversion
now = datetime.utcnow() start_date, end_date = get_date_range_in_timezone(
start_date = None date_range_filter, start_date_filter, end_date_filter,
end_date = None start_time_filter, end_time_filter, timezone_filter
)
if date_range_filter == 'today':
start_date = now.replace(hour=0, minute=0, second=0, microsecond=0)
end_date = now
elif date_range_filter == 'yesterday':
yesterday = now - timedelta(days=1)
start_date = yesterday.replace(hour=0, minute=0, second=0, microsecond=0)
end_date = yesterday.replace(hour=23, minute=59, second=59, microsecond=999999)
elif date_range_filter == 'this_week':
start_date = now - timedelta(days=now.weekday())
start_date = start_date.replace(hour=0, minute=0, second=0, microsecond=0)
end_date = now
elif date_range_filter == 'last_week':
last_week_end = now - timedelta(days=now.weekday() + 1)
last_week_start = last_week_end - timedelta(days=6)
start_date = last_week_start.replace(hour=0, minute=0, second=0, microsecond=0)
end_date = last_week_end.replace(hour=23, minute=59, second=59, microsecond=999999)
elif date_range_filter == 'this_month':
start_date = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
end_date = now
elif date_range_filter == 'all':
start_date = None
end_date = None
elif date_range_filter == 'custom':
if start_date_filter:
try:
start_date = datetime.strptime(start_date_filter, '%Y-%m-%d')
if start_time_filter:
hour, minute = map(int, start_time_filter.split(':'))
start_date = start_date.replace(hour=hour, minute=minute, second=0, microsecond=0)
else:
start_date = start_date.replace(hour=0, minute=0, second=0, microsecond=0)
except ValueError:
pass
if end_date_filter:
try:
end_date = datetime.strptime(end_date_filter, '%Y-%m-%d')
if end_time_filter:
hour, minute = map(int, end_time_filter.split(':'))
end_date = end_date.replace(hour=hour, minute=minute, second=59, microsecond=999999)
else:
end_date = end_date.replace(hour=23, minute=59, second=59, microsecond=999999)
except ValueError:
pass
# Check if user has access to this client # Check if user has access to this client
if current_user.is_admin: if current_user.is_admin:
...@@ -3269,54 +3242,11 @@ def match_report_detail(client_id, match_id): ...@@ -3269,54 +3242,11 @@ def match_report_detail(client_id, match_id):
page = request.args.get('page', 1, type=int) page = request.args.get('page', 1, type=int)
per_page = min(request.args.get('per_page', 50, type=int), 100) per_page = min(request.args.get('per_page', 50, type=int), 100)
# Calculate date range # Calculate date range based on filter with timezone conversion
now = datetime.utcnow() start_date, end_date = get_date_range_in_timezone(
start_date = None date_range_filter, start_date_filter, end_date_filter,
end_date = None start_time_filter, end_time_filter, timezone_filter
)
if date_range_filter == 'today':
start_date = now.replace(hour=0, minute=0, second=0, microsecond=0)
end_date = now
elif date_range_filter == 'yesterday':
yesterday = now - timedelta(days=1)
start_date = yesterday.replace(hour=0, minute=0, second=0, microsecond=0)
end_date = yesterday.replace(hour=23, minute=59, second=59, microsecond=999999)
elif date_range_filter == 'this_week':
start_date = now - timedelta(days=now.weekday())
start_date = start_date.replace(hour=0, minute=0, second=0, microsecond=0)
end_date = now
elif date_range_filter == 'last_week':
last_week_end = now - timedelta(days=now.weekday() + 1)
last_week_start = last_week_end - timedelta(days=6)
start_date = last_week_start.replace(hour=0, minute=0, second=0, microsecond=0)
end_date = last_week_end.replace(hour=23, minute=59, second=59, microsecond=999999)
elif date_range_filter == 'this_month':
start_date = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
end_date = now
elif date_range_filter == 'all':
start_date = None
end_date = None
elif date_range_filter == 'custom':
if start_date_filter:
try:
start_date = datetime.strptime(start_date_filter, '%Y-%m-%d')
if start_time_filter:
hour, minute = map(int, start_time_filter.split(':'))
start_date = start_date.replace(hour=hour, minute=minute, second=0, microsecond=0)
else:
start_date = start_date.replace(hour=0, minute=0, second=0, microsecond=0)
except ValueError:
pass
if end_date_filter:
try:
end_date = datetime.strptime(end_date_filter, '%Y-%m-%d')
if end_time_filter:
hour, minute = map(int, end_time_filter.split(':'))
end_date = end_date.replace(hour=hour, minute=minute, second=59, microsecond=999999)
else:
end_date = end_date.replace(hour=23, minute=59, second=59, microsecond=999999)
except ValueError:
pass
# Check if user has access to this client # Check if user has access to this client
if current_user.is_admin: if current_user.is_admin:
......
<option value="auto" {% if filters.timezone == 'auto' or not filters.timezone %}selected{% endif %}>Auto (Browser Local)</option> <option value="auto" {% if filters.timezone == 'auto' or not filters.timezone %}selected{% endif %}>Auto (Browser Local)</option>
<option value="UTC" {% if filters.timezone == 'UTC' %}selected{% endif %}>UTC</option> <option value="UTC" {% if filters.timezone == 'UTC' %}selected{% endif %}>UTC</option>
<optgroup label="UTC Offsets">
<option value="UTC-12" {% if filters.timezone == 'UTC-12' %}selected{% endif %}>UTC-12 (Baker Island)</option>
<option value="UTC-11" {% if filters.timezone == 'UTC-11' %}selected{% endif %}>UTC-11 (American Samoa)</option>
<option value="UTC-10" {% if filters.timezone == 'UTC-10' %}selected{% endif %}>UTC-10 (Hawaii)</option>
<option value="UTC-9" {% if filters.timezone == 'UTC-9' %}selected{% endif %}>UTC-9 (Alaska)</option>
<option value="UTC-8" {% if filters.timezone == 'UTC-8' %}selected{% endif %}>UTC-8 (Pacific Time)</option>
<option value="UTC-7" {% if filters.timezone == 'UTC-7' %}selected{% endif %}>UTC-7 (Mountain Time)</option>
<option value="UTC-6" {% if filters.timezone == 'UTC-6' %}selected{% endif %}>UTC-6 (Central Time)</option>
<option value="UTC-5" {% if filters.timezone == 'UTC-5' %}selected{% endif %}>UTC-5 (Eastern Time)</option>
<option value="UTC-4" {% if filters.timezone == 'UTC-4' %}selected{% endif %}>UTC-4 (Atlantic Time)</option>
<option value="UTC-3" {% if filters.timezone == 'UTC-3' %}selected{% endif %}>UTC-3 (Brazil, Argentina)</option>
<option value="UTC-2" {% if filters.timezone == 'UTC-2' %}selected{% endif %}>UTC-2 (Mid-Atlantic)</option>
<option value="UTC-1" {% if filters.timezone == 'UTC-1' %}selected{% endif %}>UTC-1 (Azores)</option>
<option value="UTC+0" {% if filters.timezone == 'UTC+0' %}selected{% endif %}>UTC+0 (GMT/UTC)</option>
<option value="UTC+1" {% if filters.timezone == 'UTC+1' %}selected{% endif %}>UTC+1 (Central European)</option>
<option value="UTC+2" {% if filters.timezone == 'UTC+2' %}selected{% endif %}>UTC+2 (Eastern European, South Africa)</option>
<option value="UTC+3" {% if filters.timezone == 'UTC+3' %}selected{% endif %}>UTC+3 (Moscow, East Africa)</option>
<option value="UTC+4" {% if filters.timezone == 'UTC+4' %}selected{% endif %}>UTC+4 (Gulf Standard)</option>
<option value="UTC+5" {% if filters.timezone == 'UTC+5' %}selected{% endif %}>UTC+5 (Pakistan)</option>
<option value="UTC+5:30" {% if filters.timezone == 'UTC+5:30' %}selected{% endif %}>UTC+5:30 (India)</option>
<option value="UTC+6" {% if filters.timezone == 'UTC+6' %}selected{% endif %}>UTC+6 (Bangladesh)</option>
<option value="UTC+7" {% if filters.timezone == 'UTC+7' %}selected{% endif %}>UTC+7 (Indochina)</option>
<option value="UTC+8" {% if filters.timezone == 'UTC+8' %}selected{% endif %}>UTC+8 (China, Singapore)</option>
<option value="UTC+9" {% if filters.timezone == 'UTC+9' %}selected{% endif %}>UTC+9 (Japan, Korea)</option>
<option value="UTC+10" {% if filters.timezone == 'UTC+10' %}selected{% endif %}>UTC+10 (Eastern Australia)</option>
<option value="UTC+11" {% if filters.timezone == 'UTC+11' %}selected{% endif %}>UTC+11 (Solomon Islands)</option>
<option value="UTC+12" {% if filters.timezone == 'UTC+12' %}selected{% endif %}>UTC+12 (New Zealand)</option>
<option value="UTC+13" {% if filters.timezone == 'UTC+13' %}selected{% endif %}>UTC+13 (Phoenix Islands)</option>
<option value="UTC+14" {% if filters.timezone == 'UTC+14' %}selected{% endif %}>UTC+14 (Line Islands)</option>
</optgroup>
<optgroup label="Africa"> <optgroup label="Africa">
<option value="Africa/Abidjan" {% if filters.timezone == 'Africa/Abidjan' %}selected{% endif %}>Abidjan</option> <option value="Africa/Abidjan" {% if filters.timezone == 'Africa/Abidjan' %}selected{% endif %}>Abidjan</option>
<option value="Africa/Accra" {% if filters.timezone == 'Africa/Accra' %}selected{% endif %}>Accra</option> <option value="Africa/Accra" {% if filters.timezone == 'Africa/Accra' %}selected{% endif %}>Accra</option>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment