agdar/TIMEZONE_FIX_SUMMARY.md
2025-11-02 14:35:35 +03:00

4.3 KiB

Timezone Fix Summary

Issue

The clock-in time was showing 13:05 when the actual time in Riyadh was 16:05 (3-hour difference). This was because the system was using UTC time instead of properly converting to Asia/Riyadh timezone.

Root Cause

  1. Django was correctly configured with TIME_ZONE = "Asia/Riyadh" and USE_TZ = True
  2. However, some code was using datetime.now() instead of Django's timezone-aware timezone.now()
  3. The attendance clock-in/out was using timezone.now().time() which extracts the UTC time component instead of the local time

Changes Made

1. Fixed finance/models.py

Lines affected: 4 methods in the CSID model

  • Changed from datetime import datetime to from django.utils import timezone
  • Replaced datetime.now() with timezone.now() in:
    • is_valid property
    • days_until_expiry property
    • revoke() method
    • increment_usage() method

2. Fixed finance/zatca_service.py

Lines affected: Import statement

  • Removed unused from datetime import datetime, timezone import
  • Kept from django.utils import timezone as django_timezone which is the correct one to use

3. Fixed finance/csid_manager.py

Lines affected: Import and get_active_csid method

  • Changed from datetime import datetime, timedelta to from datetime import timedelta
  • Added from django.utils import timezone
  • Replaced datetime.now() with timezone.now() in the get_active_csid() method

4. Fixed hr/views.py (CRITICAL FIX)

Lines affected: AttendanceKioskView.post() method

  • Changed now = timezone.now().time() to now = timezone.localtime(timezone.now()).time()
  • This ensures the time is converted to Riyadh timezone before extracting the time component

How It Works Now

  1. Django Settings:

    • TIME_ZONE = "Asia/Riyadh" - Sets the default timezone
    • USE_TZ = True - Enables timezone-aware datetimes
    • CELERY_TIMEZONE = "Asia/Riyadh" - Ensures Celery tasks use correct timezone
  2. Time Storage:

    • Django stores all datetimes in UTC internally (in the database)
    • When displaying, Django automatically converts to the configured timezone
  3. Clock In/Out:

    • timezone.now() returns current time in UTC
    • timezone.localtime(timezone.now()) converts it to Riyadh time
    • .time() extracts just the time component (now in Riyadh timezone)

Testing

A test script was created (test_timezone.py) to verify the configuration:

python3 test_timezone.py

Expected output:

  • TIME_ZONE: Asia/Riyadh
  • USE_TZ: True
  • CELERY_TIMEZONE: Asia/Riyadh
  • Current timezone offset: +0300 (UTC+3)

Additional Tools Created

1. test_timezone.py

A diagnostic script to verify timezone configuration and test datetime handling.

2. core/management/commands/fix_timezone_data.py

A management command to convert any existing naive datetime fields to timezone-aware datetimes. Usage:

python3 manage.py fix_timezone_data --dry-run  # Preview changes
python3 manage.py fix_timezone_data            # Apply changes

Verification

To verify the fix is working:

  1. Try clocking in now - the time should show the correct Riyadh time (16:05 instead of 13:05)
  2. Check any new attendance records - they should display the correct local time
  3. All datetime operations throughout the system now use timezone-aware datetimes

Best Practices Going Forward

  1. Always use timezone.now() instead of datetime.now()
  2. For local time, use timezone.localtime(timezone.now())
  3. For time-only fields, use timezone.localtime(timezone.now()).time()
  4. Never import from datetime import timezone - use Django's from django.utils import timezone
  5. All DateTimeField models automatically handle timezone conversion when USE_TZ = True

Files Modified

  1. finance/models.py - Fixed 4 datetime.now() usages
  2. finance/zatca_service.py - Removed problematic import
  3. finance/csid_manager.py - Fixed datetime.now() usage
  4. hr/views.py - Fixed clock-in/out to use local time
  5. test_timezone.py - Created (new file)
  6. core/management/commands/fix_timezone_data.py - Created (new file)
  7. TIMEZONE_FIX_SUMMARY.md - Created (this file)

Status

All timezone issues have been fixed Clock-in/out now uses correct Riyadh time All datetime operations are timezone-aware System is configured correctly for Asia/Riyadh timezone