Files
rspade_system/docs/skills/date-time/SKILL.md
root 1b46c5270c Add skills documentation and misc updates
Add form value persistence across cache revalidation re-renders

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-29 04:38:06 +00:00

245 lines
6.4 KiB
Markdown
Executable File

---
name: date-time
description: Working with dates and times in RSX using Rsx_Time and Rsx_Date classes. Use when formatting dates/times for display, handling user timezones, working with datetime columns, converting between formats, or displaying relative times like "2 hours ago".
---
# RSX Date & Time Handling
## Two Classes - Strict Separation
| Class | Purpose | Example |
|-------|---------| --------|
| `Rsx_Time` | Moments in time (with timezone) | `2025-12-24T15:30:00Z` |
| `Rsx_Date` | Calendar dates (no timezone) | `2025-12-24` |
**Critical**: Functions throw if wrong type passed (datetime to date function or vice versa). This is intentional - mixing types causes bugs.
---
## Strings, Not Objects
RSX uses ISO strings, not Carbon objects:
- **Dates**: `"2025-12-24"`
- **Datetimes**: `"2025-12-24T15:30:00Z"`
Same format in PHP, JavaScript, JSON, and database queries. No serialization surprises.
```php
$model->created_at // "2025-12-24T15:30:45.123Z" (string)
$model->due_date // "2025-12-24" (string)
Rsx_Time::now_iso() // "2025-12-24T15:30:45.123Z" (string)
```
Carbon is used internally for calculations, never exposed externally.
---
## Model Casts (Automatic)
`Rsx_Model_Abstract` auto-applies casts based on column type:
- DATE columns → `Rsx_Date_Cast`
- DATETIME columns → `Rsx_DateTime_Cast`
**Never define** `$casts` with `'date'`, `'datetime'`, or `'timestamp'` - these use Carbon and are blocked by `rsx:check`.
---
## Rsx_Time - Moments in Time
### PHP Usage
```php
use App\RSpade\Core\Time\Rsx_Time;
// Current time
Rsx_Time::now(); // Carbon (for calculations only)
Rsx_Time::now_iso(); // ISO 8601: 2025-12-24T15:30:00Z
// Formatting for display
Rsx_Time::format_datetime($datetime); // "Dec 24, 2025 3:30 PM"
Rsx_Time::format_datetime_with_tz($datetime); // "Dec 24, 2025 3:30 PM CST"
Rsx_Time::format_time($datetime); // "3:30 PM"
Rsx_Time::relative($datetime); // "2 hours ago"
// Database storage (always UTC)
Rsx_Time::to_database($datetime); // Converts to MySQL format
// Timezone
Rsx_Time::get_user_timezone(); // User's timezone or default
Rsx_Time::to_user_timezone($datetime); // Convert to user's timezone
```
### JavaScript Usage
```javascript
// Current time (synced with server)
Rsx_Time.now(); // Date object
Rsx_Time.now_iso(); // ISO string
// Formatting
Rsx_Time.format_datetime(datetime); // "Dec 24, 2025 3:30 PM"
Rsx_Time.format_datetime_with_tz(datetime); // "Dec 24, 2025 3:30 PM CST"
Rsx_Time.format_time(datetime); // "3:30 PM"
Rsx_Time.relative(datetime); // "2 hours ago", "in 3 days"
// Arithmetic
Rsx_Time.add(datetime, 3600); // Add seconds, returns ISO string
Rsx_Time.subtract(datetime, 3600); // Subtract seconds
```
---
## Rsx_Date - Calendar Dates
### PHP Usage
```php
use App\RSpade\Core\Time\Rsx_Date;
// Current date
Rsx_Date::today(); // "2025-12-24" (user's timezone)
// Formatting
Rsx_Date::format($date); // "Dec 24, 2025"
// Comparisons
Rsx_Date::is_today($date); // Boolean
Rsx_Date::is_past($date); // Boolean
Rsx_Date::is_future($date); // Boolean
Rsx_Date::diff_days($date1, $date2); // Days between
```
### JavaScript Usage
```javascript
// Current date
Rsx_Date.today(); // "2025-12-24"
// Formatting
Rsx_Date.format(date); // "Dec 24, 2025"
// Comparisons
Rsx_Date.is_today(date); // Boolean
Rsx_Date.is_past(date); // Boolean
```
---
## Live Countdown/Countup (JavaScript)
For real-time updating displays:
```javascript
// Countdown to future time
const ctrl = Rsx_Time.countdown(this.$sid('timer'), deadline, {
short: true, // "2h 30m" vs "2 hours and 30 minutes"
on_complete: () => this.reload()
});
// Stop countdown when leaving page
this.on_stop(() => ctrl.stop());
// Countup from past time (elapsed time)
Rsx_Time.countup(this.$sid('elapsed'), started_at, { short: true });
```
---
## Server Time Sync
Client time syncs automatically via `rsxapp` data on page load and AJAX responses. No manual sync required.
```javascript
// Client always has accurate server time
const server_now = Rsx_Time.now(); // Synced with server, corrects for clock skew
```
---
## User Timezone
Stored in `login_users.timezone` (IANA format, e.g., `America/Chicago`).
Falls back to `config('rsx.datetime.default_timezone')`.
```php
// Get user's timezone
$tz = Rsx_Time::get_user_timezone();
// All Rsx_Time methods automatically use user's timezone for display
```
---
## Component Expectations
### Date_Picker Component
- `val()` returns `"YYYY-MM-DD"` or `null`
- `val(value)` accepts `"YYYY-MM-DD"` or `null`
- **Throws** if passed datetime format
- Display shows localized format (e.g., "Dec 24, 2025")
### Datetime_Picker Component
- `val()` returns ISO 8601 string or `null`
- `val(value)` accepts ISO 8601 string or `null`
- **Throws** if passed date-only format
- Display shows localized time in user's timezone
---
## Common Patterns
### Display in Template
```jqhtml
<span><%= Rsx_Time.format_datetime(this.data.record.created_at) %></span>
<span><%= Rsx_Time.relative(this.data.record.updated_at) %></span>
<span><%= Rsx_Date.format(this.data.record.due_date) %></span>
```
### Conditional Display
```jqhtml
<% if (Rsx_Date.is_past(this.data.task.due_date)) { %>
<span class="text-danger">Overdue</span>
<% } %>
```
### Save to Database
```php
// Datetime - store in UTC
$record->scheduled_at = Rsx_Time::to_database($params['scheduled_at']);
// Date - store as-is
$record->due_date = $params['due_date']; // Already "YYYY-MM-DD"
```
### Parse User Input
```php
// If user enters a datetime string
$datetime = Rsx_Time::parse($params['datetime']); // Returns Carbon
$iso = Rsx_Time::to_iso($datetime); // Convert back to string
// If user enters a date string
$date = Rsx_Date::parse($params['date']); // Returns "YYYY-MM-DD"
```
---
## Key Rules
1. **Never use Carbon directly** - RSX uses string-based dates
2. **Never use PHP's date()** - Use Rsx_Time/Rsx_Date
3. **Store datetimes in UTC** - Use `Rsx_Time::to_database()`
4. **Display in user's timezone** - Automatic via Rsx_Time format methods
5. **Dates have no timezone** - Use Rsx_Date for calendar dates
6. **Wrong types throw** - Date functions reject datetimes and vice versa
## More Information
Details: `php artisan rsx:man time`