PHP 與 Java 日期時間 API 對照表:格式化、解析、運算一覽無遺
雙語言開發或遷移專案時,日期時間處理是高頻痛點。本文將 PHP date()/strtotime()/DateTime 與 Java java.time (JSR-310) / SimpleDateFormat 核心 API 做逐項對照,附帶常用格式字串對照表與時區處理最佳實踐。
一、核心 API 對照速查
| 功能 | PHP (傳統) | PHP (OO DateTime) | Java (Legacy) | Java (java.time) |
| 當前時間 | time() | new DateTime() | new Date() | LocalDateTime.now() |
| 格式化輸出 | date('Y-m-d H:i:s') | $dt->format('Y-m-d H:i:s') | sdf.format(date) | dtf.format(ldt) |
| 字串解析 | strtotime('2023-01-01') | DateTime::createFromFormat() | sdf.parse(str) | ldt.parse(str, dtf) |
| 時間戳(秒) | time() | $dt->getTimestamp() | date.getTime()/1000 | ldt.toEpochSecond(zone) |
| 時間戳(毫秒) | microtime(true)*1000 | $dt->format('Uv') | date.getTime() | ldt.toInstant(zone).toEpochMilli() |
| 加減天數 | strtotime('+1 day') | $dt->modify('+1 day') | cal.add(Calendar.DAY,1) | ldt.plusDays(1) |
| 差值計算 | $dt1->diff($dt2) | DateInterval | ChronoUnit.DAYS.between() | Duration.between() |
| 時區轉換 | $dt->setTimezone(new DateTimeZone('UTC')) | 同上 | sdf.setTimeZone(tz) | zdt.withZoneSameInstant(zone) |
二、格式字串對照表(高頻項)
| 含義 | PHP | Java (SimpleDateFormat / DateTimeFormatter) |
| 年(4位) | Y | yyyy |
| 月(2位) | m | MM |
| 日(2位) | d | dd |
| 時(24制,2位) | H | HH |
| 分(2位) | i | mm |
| 秒(2位) | s | ss |
| 毫秒(3位) | u (PHP 7.1+) | SSS |
| 星期(全名) | l | EEEE |
| 時區偏移 | P (PHP 5.1+) | XXX |
三、PHP 實戰範例
<?php
// 1. 當前時間
echo date('Y-m-d H:i:s'); // 2024-05-20 14:30:00
echo (new DateTime())->format('c'); // ISO 8601: 2024-05-20T14:30:00+08:00
// 2. 相對時間運算 (strtotime 風格)
echo date('Y-m-d', strtotime('-1 day')); // 昨天
echo date('Y-m-d', strtotime('+1 week')); // 下周
echo date('Y-m-d', strtotime('first day of next month')); // 下月1號
// 3. DateTime 物件風格 (推薦)
$dt = new DateTime('2024-05-20 14:30:00', new DateTimeZone('Asia/Taipei'));
$dt->modify('+2 hours 30 minutes');
$dt->setTimezone(new DateTimeZone('UTC'));
echo $dt->format('Y-m-d H:i:s P'); // 2024-05-20 09:00:00 +00:00
// 4. 計算差值
$dt1 = new DateTime('2024-01-01');
$dt2 = new DateTime('2024-12-31');
$diff = $dt1->diff($dt2);
echo $diff->format('%a 天 %h 小時'); // 364 天 0 小時
?>
四、Java 實戰範例 (java.time)
import java.time.*;
import java.time.format.DateTimeFormatter;
public class Demo {
public static void main(String[] args) {
// 1. 當前時間 + 格式化
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime now = LocalDateTime.now();
System.out.println(dtf.format(now));
// 2. 解析
LocalDateTime parsed = LocalDateTime.parse("2024-05-20 14:30:00", dtf);
// 3. 運算
System.out.println(now.plusDays(1)); // 明天
System.out.println(now.minusWeeks(1)); // 上周
System.out.println(now.with(TemporalAdjusters.firstDayOfNextMonth())); // 下月1號
// 4. 時區轉換
ZonedDateTime taipei = now.atZone(ZoneId.of("Asia/Taipei"));
ZonedDateTime utc = taipei.withZoneSameInstant(ZoneOffset.UTC);
System.out.println(utc.format(dtf));
// 5. 差值
long days = ChronoUnit.DAYS.between(LocalDate.of(2024,1,1), LocalDate.of(2024,12,31));
System.out.println(days + " 天");
}
}
五、遷移與互操作關鍵點
- 時間戳傳輸: 雙端統一用 毫秒級 Unix Timestamp (Long),JSON 傳輸無歧義
- ISO 8601 字串:
2024-05-20T14:30:00+08:00 雙端原生支援解析,含時區資訊
- 資料庫存儲: 推薦
TIMESTAMP WITH TIME ZONE (PostgreSQL) / DATETIME(6) + 應用層統一 UTC
- PHP 避坑:
strtotime 對 "next Monday" 等英文關鍵字敏感,跨語系環境請改用 DateTime::modify 或指定格式解析