110 lines
4.3 KiB
Markdown
110 lines
4.3 KiB
Markdown
# 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:
|
|
```bash
|
|
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:
|
|
```bash
|
|
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
|