|
| 1 | +# DateTime Modernization Update |
| 2 | + |
| 3 | +## Summary |
| 4 | +Updated the Subscription Tracker codebase to use modern Python datetime practices by replacing deprecated `datetime.utcnow()` with `datetime.now(timezone.utc)`. |
| 5 | + |
| 6 | +## Changes Made |
| 7 | + |
| 8 | +### ✅ Files Updated |
| 9 | + |
| 10 | +1. **`app/webhooks.py`** |
| 11 | + - Added `timezone` import |
| 12 | + - Updated webhook timestamp generation |
| 13 | + - Updated last_used timestamp tracking |
| 14 | + - Fixed Discord, Slack, and Generic webhook timestamp formats |
| 15 | + |
| 16 | +2. **`app/currency.py`** |
| 17 | + - Added `timezone` import |
| 18 | + - Updated cache age calculations for currency rates |
| 19 | + - Fixed timezone-aware datetime comparisons |
| 20 | + |
| 21 | +3. **`app/models.py`** |
| 22 | + - Added `timezone` import |
| 23 | + - Updated database column defaults for: |
| 24 | + - `Webhook.created_at` |
| 25 | + - `ExchangeRate.created_at` |
| 26 | + - `PaymentMethod.created_at` |
| 27 | + - Fixed `ExchangeRate.save_rates()` method |
| 28 | + |
| 29 | +### 🔧 Technical Details |
| 30 | + |
| 31 | +#### Before (Deprecated): |
| 32 | +```python |
| 33 | +datetime.utcnow() # Returns naive datetime in UTC |
| 34 | +created_at = db.Column(db.DateTime, default=datetime.utcnow) |
| 35 | +``` |
| 36 | + |
| 37 | +#### After (Modern): |
| 38 | +```python |
| 39 | +datetime.now(timezone.utc) # Returns timezone-aware datetime in UTC |
| 40 | +created_at = db.Column(db.DateTime, default=lambda: datetime.now(timezone.utc)) |
| 41 | +``` |
| 42 | + |
| 43 | +### 📝 Key Improvements |
| 44 | + |
| 45 | +1. **Timezone Awareness**: All UTC timestamps are now timezone-aware |
| 46 | +2. **Future Compatibility**: Avoids deprecation warnings in Python 3.12+ |
| 47 | +3. **Database Compatibility**: Lambda functions ensure fresh timestamps per record |
| 48 | +4. **Consistency**: Uniform approach across all modules |
| 49 | + |
| 50 | +### 🔍 Remaining `datetime.now()` Usage |
| 51 | + |
| 52 | +The following `datetime.now()` calls remain unchanged as they are used for local time operations: |
| 53 | + |
| 54 | +- **Display formatting**: User-facing timestamp displays |
| 55 | +- **Local date comparisons**: Subscription expiry checks relative to user's local date |
| 56 | +- **Health check timestamps**: Application status timestamps |
| 57 | +- **Circuit breaker timestamps**: Internal timeout tracking |
| 58 | + |
| 59 | +These are intentionally kept as local time since they represent user-facing functionality or internal timers. |
| 60 | + |
| 61 | +### 🧪 Testing |
| 62 | + |
| 63 | +After this update, ensure: |
| 64 | + |
| 65 | +1. **Webhook timestamps** appear correctly in your webhook destinations |
| 66 | +2. **Database records** have proper created_at timestamps |
| 67 | +3. **Currency rate caching** works correctly with age calculations |
| 68 | +4. **No deprecation warnings** appear in Python 3.12+ environments |
| 69 | + |
| 70 | +### 🚀 Migration Notes |
| 71 | + |
| 72 | +This is a **forward-compatible** change: |
| 73 | +- Existing database records are unaffected |
| 74 | +- All new records will use timezone-aware timestamps |
| 75 | +- No data migration required |
| 76 | +- Backward compatible with existing functionality |
| 77 | + |
| 78 | +### 📚 References |
| 79 | + |
| 80 | +- [Python datetime documentation](https://docs.python.org/3/library/datetime.html) |
| 81 | +- [PEP 615 – Support for the IANA Time Zone Database](https://peps.python.org/pep-0615/) |
| 82 | +- [Python 3.12 datetime deprecations](https://docs.python.org/3.12/whatsnew/3.12.html#deprecated) |
| 83 | + |
| 84 | +## Verification |
| 85 | + |
| 86 | +Run the application and verify: |
| 87 | +```bash |
| 88 | +# No deprecation warnings should appear |
| 89 | +docker-compose up --build |
| 90 | + |
| 91 | +# Test webhook functionality |
| 92 | +./test-webhook.sh discord "your-webhook-url" |
| 93 | + |
| 94 | +# Check database timestamps are timezone-aware |
| 95 | +# (New records should have proper UTC timestamps) |
| 96 | +``` |
| 97 | + |
| 98 | +This update ensures the Subscription Tracker remains compatible with current and future Python versions while maintaining all existing functionality. |
0 commit comments