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

6.4 KiB
Executable File

name, description
name description
date-time 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.

$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

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

// 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

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

// 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:

// 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.

// 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').

// 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

<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

<% if (Rsx_Date.is_past(this.data.task.due_date)) { %>
    <span class="text-danger">Overdue</span>
<% } %>

Save to Database

// 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

// 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