arraypress/wp-date-utils 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

arraypress/wp-date-utils

Composer 安装命令:

composer require arraypress/wp-date-utils

包简介

Lightweight WordPress date utilities with UTC storage, local display, and zero dependencies. Handles date ranges, business logic, subscriptions, and formatting.

README 文档

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 - 12 essential predefined ranges (today, last week, last 90 days, etc.)
  • Date Math - Add/subtract days, hours, months with precision
  • Business Logic - Weekend/business day checking, age calculation
  • Subscription Periods - Handle billing cycles with Stripe compatibility
  • Formatting - WordPress date/time settings with i18n support
  • Validation - Date format checking, expiration logic, freshness checks
  • Database Helpers - Query builders for date ranges
  • Lightweight - ~450 lines vs thousands with Carbon
  • WordPress Native - Built on wp_date(), get_gmt_from_date(), etc.

Installation

composer require arraypress/wp-date-utils

Basic Usage

use ArrayPress\DateUtils\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"

// Format with empty handling
echo Dates::format_or_empty( $date );            // Shows "—" if empty
echo Dates::format_or_empty( $date, 'Never', 'human' );  // "Never" for empty dates

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( 'year_to_date' );

// Essential ranges available:
// today, yesterday
// this_week, last_week
// this_month, last_month
// this_year, last_year
// last_7_days, last_30_days, last_90_days
// year_to_date

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

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

Date Math

// Add time (uses precise DateTime for months/years)
$future = Dates::add( $utc_date, 7, 'days' );
$future = Dates::add( $utc_date, 2, 'hours' );
$future = Dates::add( $utc_date, 1, 'months' );   // Precise month calculation
$future = Dates::add( $utc_date, 1, 'years' );    // Handles leap years

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

// Direct month/year arithmetic
$next_month = Dates::add_months( $utc_date, 1 );
$next_year = Dates::add_years( $utc_date, 1 );

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

// Get elapsed time
$hours_ago = Dates::elapsed( $utc_date, 'hours' );  // null if invalid

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

Validation & Checks

// Date validation
if ( Dates::is_valid( $date_string ) ) {}
if ( Dates::is_format( $date, 'Y-m-d' ) ) {}

// Date checks
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 ) ) {}

// Freshness checks
if ( Dates::is_stale( $last_sync, 24, 'hours' ) ) {
    // Data is older than 24 hours or empty
}

if ( Dates::is_fresh( $cache_time, 1, 'hours' ) ) {
    // Cache is less than 1 hour old and valid
}

// Age calculation
$age = Dates::get_age( $birth_date_utc );

Business Logic

// Weekend/business day checking
if ( Dates::is_weekend( $utc_date ) ) {}
if ( Dates::is_business_day( $utc_date ) ) {}

// Custom business days (1=Mon, 7=Sun)
$custom_days = [1, 2, 3, 4, 5, 6]; // Mon-Sat
if ( Dates::is_business_day( $utc_date, $custom_days ) ) {}

// Get next business day
$next = Dates::next_business_day( $utc_date );
$next = Dates::next_business_day( $utc_date, [1, 2, 3, 4, 5] );

Date Boundaries

// Get start/end of day
$start = Dates::start_of_day( $utc_date );  // "2025-01-15 00:00:00"
$end = Dates::end_of_day( $utc_date );      // "2025-01-15 23:59:59"

Subscriptions & Billing

// Calculate next billing date (uses precise month/year arithmetic)
$next = Dates::next_billing( $last_payment, 'monthly' );
$next = Dates::next_billing( $last_payment, 'yearly' );
$next = Dates::next_billing( $last_payment, 'every_3_months' );

// Stripe-compatible periods
$periods = Dates::get_period_options();
// Returns: daily, weekly, monthly, every_3_months, every_6_months, yearly

// Include custom option for UI
$periods = Dates::get_period_options( true );  // Adds 'custom' option

// Convert to Stripe format
$stripe = Dates::get_stripe_interval( 'every_3_months' );
// Returns: ['interval' => 'month', 'interval_count' => 3]

Timestamp Conversion

// Convert Unix timestamp to MySQL
$mysql_date = Dates::timestamp_to_mysql( $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>"

Database Integration

// Build date range queries
$query = Dates::build_date_query( 'created_at', $start_local, $end_local );

$results = $wpdb->get_results( $wpdb->prepare(
    "SELECT * FROM orders WHERE {$query['sql']}",
    ...$query['values']
) );

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"

// Display with empty handling
echo Dates::format_or_empty( $event->deleted_at, 'Not deleted', 'human' );

Date Range Queries

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

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

Data Freshness Checking

class API_Cache {
    public function get_data() {
        $cached_at = get_option( 'api_cache_time' );
        
        // Check if cache is stale (older than 1 hour)
        if ( Dates::is_stale( $cached_at, 1, 'hours' ) ) {
            $data = $this->fetch_from_api();
            update_option( 'api_cache_time', Dates::now_utc() );
            return $data;
        }
        
        return get_option( 'api_cache_data' );
    }
}

Subscription Management

// Calculate next billing with Stripe-compatible periods
$subscription = get_subscription( $user_id );
$next_billing = Dates::next_billing( $subscription->last_payment, 'every_3_months' );

// Convert for Stripe API
$stripe_interval = Dates::get_stripe_interval( 'every_3_months' );
\Stripe\Subscription::create([
    'customer' => $customer_id,
    'items' => [['price' => $price_id]],
    'recurring' => $stripe_interval
]);

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

Admin Table Column

public function column_created( $item ) {
    // Properly converts UTC to local and formats
    return Dates::format( $item['created_at'] );
    
    // Or with admin formatting (includes relative time)
    return Dates::format_admin( $item['created_at'] );
}

public function column_last_sync( $item ) {
    // Shows "Never" for empty dates
    return Dates::format_or_empty( $item['last_sync_at'], 'Never', 'human' );
}

Method Reference

Core Operations

  • now_utc() - Current UTC time
  • now_local() - Current local time
  • to_utc() - Convert local to UTC
  • to_local() - Convert UTC to local

Date Math

  • add() - Add time units
  • subtract() - Subtract time units
  • add_months() - Precise month addition
  • add_years() - Precise year addition
  • diff() - Get difference between dates
  • elapsed() - Get elapsed time since date

Formatting

  • format() - WordPress format with i18n
  • human_diff() - Human readable difference
  • format_admin() - Admin display with relative time
  • format_or_empty() - Format with empty value handling

Validation

  • is_valid() - Validate date string
  • is_format() - Check specific format
  • is_expired() - Check expiration with grace period
  • is_future() / is_past() - Time comparisons
  • is_zero() - Check for empty/zero dates
  • in_range() - Check if date within range
  • is_stale() - Check if older than threshold
  • is_fresh() - Check if within threshold

Business Logic

  • is_weekend() / is_business_day() - Day type checking
  • next_business_day() - Skip to next business day
  • get_age() - Calculate age from birth date

Date Ranges

  • get_range() - Get predefined ranges
  • range_to_utc() - Convert local range to UTC
  • start_of_day() / end_of_day() - Day boundaries

Subscription & Billing

  • next_billing() - Calculate next billing date
  • get_period_options() - Get period dropdown options
  • get_stripe_interval() - Convert to Stripe format
  • calculate_expiration() - Calculate future expiration

Utilities

  • timestamp_to_mysql() - Unix timestamp to MySQL
  • to_timestamp() - MySQL to Unix timestamp
  • build_date_query() - Database query builder
  • get_range_options() - Get range dropdown options

Why Not Carbon?

This library is intentionally lightweight:

  • Performance: No heavy dependency loading
  • Size: ~450 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
  • Maintenance: Fewer dependencies to manage

Requirements

  • PHP 7.4 or higher
  • WordPress 5.3 or higher (for wp_timezone())

License

GPL-2.0-or-later

Support

统计信息

  • 总下载量: 13
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 0
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: GPL-2.0-or-later
  • 更新时间: 2025-09-02