arraypress/wp-dates

Lightweight date utilities for WordPress focusing on UTC storage and local display without external dependencies.

dev-main 2025-09-05 14:48 UTC

This package is auto-updated.

Last update: 2025-09-05 14:49:36 UTC


README

Lightweight date utilities for WordPress focusing on UTC storage and local display without external dependencies.

Features

  • 🚀 Zero Dependencies - Uses only WordPress core and PHP built-ins
  • 🌍 UTC Storage - Store dates safely in UTC for database
  • 📍 Local Display - Convert to site timezone for display
  • 📅 Date Ranges - 25+ predefined ranges (today, last week, last 90 days, etc.)
  • Date Math - Add/subtract days, hours, months from dates
  • 💳 Stripe Ready - Convert Unix timestamps to MySQL format
  • 📊 Subscription Periods - Handle billing cycles (daily, monthly, yearly)
  • 🎨 Formatting - WordPress date/time settings with i18n support
  • Lightweight - ~400 lines vs thousands with Carbon
  • 🔧 WordPress Native - Built on wp_date(), get_gmt_from_date(), etc.

Installation

composer require arraypress/wp-dates

Basic Usage

use ArrayPress\Dates\Dates;

// Current times
$utc_now   = Dates::now_utc();        // For database storage
$local_now = Dates::now_local();    // For display

// Convert between UTC and local
$utc   = Dates::to_utc( $user_input );           // Store in DB
$local = Dates::to_local( $database_value );   // Display to user

// Format dates
echo Dates::format( $utc_date );            // Uses WP settings
echo Dates::format( $utc_date, 'date' );    // Date only
echo Dates::format( $utc_date, 'time' );    // Time only

// Human-readable
echo Dates::human_diff( $utc_date );  // "2 hours ago"

Date Ranges

// Get predefined ranges (returns UTC start/end)
$range = Dates::get_range( 'today' );
$range = Dates::get_range( 'last_week' );
$range = Dates::get_range( 'last_30_days' );
$range = Dates::get_range( 'last_quarter' );
$range = Dates::get_range( 'year_to_date' );

// Available ranges:
// today, yesterday, tomorrow
// this_week, last_week, next_week
// this_month, last_month, next_month
// this_quarter, last_quarter
// this_year, last_year, next_year
// last_7_days, last_30_days, last_60_days, last_90_days
// last_180_days, last_365_days
// year_to_date, month_to_date, week_to_date

// Returns: ['start' => '2025-01-01 00:00:00', 'end' => '2025-01-31 23:59:59']

Date Math

// Add time
$future = Dates::add( $utc_date, 7, 'days' );
$future = Dates::add( $utc_date, 2, 'hours' );
$future = Dates::add( $utc_date, 1, 'months' );

// Subtract time
$past = Dates::subtract( $utc_date, 30, 'days' );
$past = Dates::subtract( $utc_date, 6, 'months' );

// Get difference
$days  = Dates::diff( $date1, $date2, 'days' );
$hours = Dates::diff( $date1, $date2, 'hours' );

// Calculate expiration
$expires = Dates::calculate_expiration( 30, 'days' );
$expires = Dates::calculate_expiration( 1, 'years' );

Validation & Checks

// Check dates
if ( Dates::is_expired( $utc_date ) ) {}
if ( Dates::is_expired( $utc_date, 24 ) ) {}  // With 24-hour grace period
if ( Dates::is_future( $utc_date ) ) {}
if ( Dates::is_past( $utc_date ) ) {}
if ( Dates::is_zero( $date ) ) {}  // Check for 0000-00-00
if ( Dates::in_range( $date, $start, $end ) ) {}

Subscriptions & Billing

// Calculate next billing date
$next = Dates::next_billing( $last_payment, 'monthly' );
$next = Dates::next_billing( $last_payment, 'yearly' );

// Available periods: daily, weekly, monthly, quarterly, biannual, yearly

// Get period options for dropdowns
$periods = Dates::get_period_options();

Stripe Integration

// Convert Stripe timestamp to MySQL
$mysql_date = Dates::stripe_to_mysql( $stripe_timestamp );

// Convert MySQL to timestamp
$timestamp = Dates::to_timestamp( $mysql_date );

Admin Display

// Format for admin with relative time
echo Dates::format_admin( $utc_date );
// Outputs: "Jan 15, 2025 10:30 AM<br><small>2 hours ago</small>"

Timezone Handling

// Ranges calculate in local timezone by default
$today = Dates::get_range( 'today' );  // Today in site timezone, returned as UTC

// Or use pure UTC calculation (for rolling windows)
$last_30 = Dates::get_range( 'last_30_days', false );  // Pure UTC

// Convert custom local range to UTC
$utc_range = Dates::range_to_utc( '2025-01-15 00:00:00', '2025-01-15 23:59:59' );

Dropdown Options

// Get range options for select fields
$ranges = Dates::get_range_options();
foreach ( $ranges as $value => $label ) {
	echo "<option value='$value'>$label</option>";
}

Real-World Examples

Storing User Input

// User submits date in their timezone
$user_date = $_POST['event_date'];  // "2025-01-15 14:30:00"

// Convert to UTC for database
$utc_date = Dates::to_utc( $user_date );

// Store in database
$wpdb->insert( $table, [ 'event_date' => $utc_date ] );

Displaying Dates

// Get from database (stored as UTC)
$event = $wpdb->get_row( "SELECT * FROM events WHERE id = 1" );

// Display in user's timezone
echo Dates::format( $event->event_date );  // "Jan 15, 2025 2:30 PM"
echo Dates::human_diff( $event->created_at );  // "3 days ago"

Date Range Queries

// User selects "Last 30 Days" 
$range = Dates::get_range( 'last_30_days' );

// Query database
$results = $wpdb->get_results( $wpdb->prepare(
	"SELECT * FROM orders WHERE created_at BETWEEN %s AND %s",
	$range['start'],
	$range['end']
) );

Subscription Management

// Calculate next billing
$subscription = get_subscription( $user_id );
$next_billing = Dates::next_billing( $subscription->last_payment, 'monthly' );

// Check if expired
if ( Dates::is_expired( $subscription->expires_at, 72 ) ) {  // 72-hour grace
	cancel_subscription( $user_id );
}

Why Not Carbon?

This library is intentionally lightweight:

  • Performance: No heavy dependency loading
  • Size: ~400 lines vs Carbon's thousands
  • Simplicity: Does exactly what WordPress needs
  • Native: Uses WordPress's own date functions
  • Sufficient: Covers 99% of WordPress date needs

Requirements

  • PHP 7.4 or higher
  • WordPress 5.3 or higher

License

GPL-2.0-or-later

Support