# Timestamping Rules

## Overview

This rule ensures consistent timestamping across the Trax project using proper datetime functions and standardized formats.

## Core Rule: Always Use DateTime Functions

### ✅ DO: Use datetime functions for timestamps
```python
from datetime import datetime, timezone

# For current timestamp
current_time = datetime.now(timezone.utc)

# For database timestamps
created_at = datetime.now(timezone.utc)
updated_at = datetime.now(timezone.utc)

# For file timestamps
timestamp = datetime.now(timezone.utc).strftime("%Y-%m-%d_%H-%M-%S")
```

### ❌ DON'T: Hardcode dates or use manual timestamps
```python
# WRONG - Hardcoded date
created_at = "2024-12-20"

# WRONG - Manual timestamp
timestamp = "2024-12-20 14:30:00"

# WRONG - No timezone
current_time = datetime.now()  # Missing timezone
```

## Timestamping Standards

### 1. Database Timestamps
```python
from datetime import datetime, timezone
from sqlalchemy import Column, DateTime

class BaseModel:
    created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc))
    updated_at = Column(DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc))
```

### 2. File Naming
```python
from datetime import datetime, timezone

def generate_timestamped_filename(prefix: str, extension: str) -> str:
    timestamp = datetime.now(timezone.utc).strftime("%Y%m%d_%H%M%S")
    return f"{prefix}_{timestamp}.{extension}"

# Usage
filename = generate_timestamped_filename("transcript", "json")
# Result: transcript_20241220_143052.json
```

### 3. Log Messages
```python
import logging
from datetime import datetime, timezone

def log_with_timestamp(message: str, level: str = "INFO"):
    timestamp = datetime.now(timezone.utc).isoformat()
    logging.log(getattr(logging, level), f"[{timestamp}] {message}")

# Usage
log_with_timestamp("Processing started", "INFO")
# Result: [2024-12-20T14:30:52.123456+00:00] Processing started
```

### 4. API Responses
```python
from datetime import datetime, timezone
from typing import Dict, Any

def create_api_response(data: Any, status: str = "success") -> Dict[str, Any]:
    return {
        "data": data,
        "status": status,
        "timestamp": datetime.now(timezone.utc).isoformat(),
        "version": "1.0.0"
    }
```

### 5. Cache Keys
```python
from datetime import datetime, timezone

def generate_cache_key(prefix: str, identifier: str) -> str:
    timestamp = datetime.now(timezone.utc).strftime("%Y%m%d_%H%M")
    return f"{prefix}:{identifier}:{timestamp}"

# Usage
cache_key = generate_cache_key("transcript", "abc123")
# Result: transcript:abc123:20241220_1430
```

## Timezone Handling

### Always Use UTC
```python
# ✅ Correct - Always UTC
from datetime import datetime, timezone

current_utc = datetime.now(timezone.utc)
timestamp_utc = current_utc.isoformat()

# ❌ Wrong - Local timezone
current_local = datetime.now()  # System timezone
```

### Timezone Conversion (When Needed)
```python
from datetime import datetime, timezone
import pytz

# Store in UTC, convert for display
utc_time = datetime.now(timezone.utc)
pacific_tz = pytz.timezone('US/Pacific')
pacific_time = utc_time.astimezone(pacific_tz)
```

## Format Standards

### ISO 8601 for Storage
```python
# Database and API storage
timestamp = datetime.now(timezone.utc).isoformat()
# Result: 2024-12-20T14:30:52.123456+00:00
```

### Human Readable for Display
```python
# User-facing timestamps
timestamp = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S UTC")
# Result: 2024-12-20 14:30:52 UTC
```

### File System Safe
```python
# File names and paths
timestamp = datetime.now(timezone.utc).strftime("%Y%m%d_%H%M%S")
# Result: 20241220_143052
```

## Database Migration Timestamps

### Migration Files
```python
# alembic/versions/001_create_initial_schema.py
"""create initial schema

Revision ID: 001
Revises: 
Create Date: 2024-12-20 14:30:52.123456

"""
from alembic import op
import sqlalchemy as sa
from datetime import datetime, timezone

# Use function for revision date
revision = '001'
down_revision = None
branch_labels = None
depends_on = None

def upgrade():
    # Migration logic here
    pass

def downgrade():
    # Rollback logic here
    pass
```

## Testing Timestamps

### Test Fixtures
```python
import pytest
from datetime import datetime, timezone

@pytest.fixture
def sample_timestamp():
    """Provide consistent timestamp for tests"""
    return datetime.now(timezone.utc)

@pytest.fixture
def sample_media_file():
    """Create test media file with timestamp"""
    timestamp = datetime.now(timezone.utc).strftime("%Y%m%d_%H%M%S")
    return f"test_audio_{timestamp}.wav"
```

## Validation Functions

### Timestamp Validation
```python
from datetime import datetime, timezone
from typing import Optional

def validate_timestamp(timestamp: Optional[datetime]) -> bool:
    """Validate that timestamp is UTC and not in the future"""
    if timestamp is None:
        return False
    
    # Check timezone
    if timestamp.tzinfo != timezone.utc:
        return False
    
    # Check not in future
    if timestamp > datetime.now(timezone.utc):
        return False
    
    return True

def normalize_timestamp(timestamp: datetime) -> datetime:
    """Ensure timestamp is in UTC"""
    if timestamp.tzinfo is None:
        # Assume UTC if no timezone
        return timestamp.replace(tzinfo=timezone.utc)
    elif timestamp.tzinfo != timezone.utc:
        # Convert to UTC
        return timestamp.astimezone(timezone.utc)
    else:
        return timestamp
```

## Error Handling

### Invalid Timestamps
```python
from datetime import datetime, timezone

def safe_timestamp() -> datetime:
    """Safely get current timestamp with error handling"""
    try:
        return datetime.now(timezone.utc)
    except Exception as e:
        # Fallback to system time if needed
        fallback = datetime.now()
        return fallback.replace(tzinfo=timezone.utc)
```

## Compliance Checklist

When adding timestamps to the project:

- [ ] Use `datetime.now(timezone.utc)` for current time
- [ ] Store timestamps in ISO 8601 format
- [ ] Include timezone information (always UTC)
- [ ] Use consistent naming conventions
- [ ] Validate timestamps in tests
- [ ] Handle timezone conversion properly
- [ ] Use appropriate format for context (storage vs display)

## Examples by Context

### Database Models
```python
from sqlalchemy import Column, DateTime
from datetime import datetime, timezone

class Transcript(Base):
    __tablename__ = 'transcripts'
    
    id = Column(UUID, primary_key=True)
    created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc))
    updated_at = Column(DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc))
```

### Configuration Files
```python
# config.py
from datetime import datetime, timezone

CONFIG_METADATA = {
    "last_updated": datetime.now(timezone.utc).isoformat(),
    "version": "1.0.0"
}
```

### Log Files
```python
# logging_config.py
import logging
from datetime import datetime, timezone

class TimestampFormatter(logging.Formatter):
    def format(self, record):
        record.timestamp = datetime.now(timezone.utc).isoformat()
        return super().format(record)
```

---

*Rule Version: 1.0*  
*Last Updated: 2024-12-20*  
*Enforcement: Required for all timestamp operations*
