SPIRAL APIで取得したレコードの日付や時刻フィールド。
「そのままでは比較しづらい」「表示形式を手軽に変えたい」と感じたことはありませんか?
特に、日時、日付、月日、時刻 など、複数のフィールドタイプを統一的に扱うのは意外と手間がかかります。
この記事では、そんな日付・時刻の処理を劇的に楽にする、コピペで使えるPHPのお役立ち関数セットを紹介します。
この関数をPHPファイルに設置するだけで、日付のフォーマット変更、和暦変換、相対時間表示などが一行で実現できます。
この関数で出来ること
- 日付・時刻文字列をPHPの標準オブジェクトに変換
- 「2025年10月09日 (木)」のような曜日付きフォーマット
- 「令和7年10月9日」のような和暦表示
- 「午前 9時30分」のような12時間表記
- 「3時間前」「5日後」のような相対時間表示
- 指定した日付が週末かどうかの判定
実装の概要
今回のコードでは、以下の流れで処理を行います。
2. スクリプト上部の設定エリアで、ご自身のDBのフィールド識別名を指定します。
3. あとは、サンプルコードを参考に、使いたい関数を呼び出すだけです。
お役立ち関数コード
以下のPHPコードを、お使いのPHPスクリプトの任意の位置(クラス定義の外など)にコピーして貼り付けてください。
コピー
//------------------------------
// 日付・時刻お役立ち関数
//------------------------------
/**
* SPIRAL APIから取得した日付文字列を、指定したフォーマットの文字列に変換します。
* 曜日の日本語表示など、よく使う形式を簡単に呼び出せます。
*
* @param ?string $value APIから取得した日付・時刻文字列。
* @param string $type フィールドタイプ ('date', 'monthDay', 'time', 'dateTime')。
* @param string $format 出力フォーマット。'Y-m-d', 'Y年m月d日', 'Y/m/d (w_jp)' など。
* 'w_jp' を含めると、その部分が日本語の曜日に置き換わります (例: 日, 月)。
* @return ?string フォーマットされた日付文字列。変換できない場合はnullを返します。
*/
function formatSpiralDateTime(?string $value, string $type, string $format, string $timezone = 'Asia/Tokyo'): ?string
{
$dateObj = parseSpiralDateTime($value, $type);
if ($dateObj === null) {
return null;
}
// dateTime型の場合は、指定されたタイムゾーンに変換
if ($type === 'dateTime') {
$dateObj = $dateObj->setTimezone(new DateTimeZone($timezone));
}
// 午前/午後付き12時間表記
if (strpos($format, 'g_jp') !== false) {
$am_pm = ((int)$dateObj->format('G') < 12) ? '午前' : '午後';
$format = str_replace('g_jp', $am_pm, $format);
}
// フォーマットに 'w_jp' が含まれている場合、日本語の曜日に置換する
if (strpos($format, 'w_jp') !== false) {
$week = ['日', '月', '火', '水', '木', '金', '土'];
$dayOfWeek = $week[(int)$dateObj->format('w')];
$format = str_replace('w_jp', $dayOfWeek, $format);
}
return $dateObj->format($format);
}
/**
* 指定された日時文字列と現在時刻との差を「〇分前」「〇日後」のような相対時間で返します。
*
* @param ?string $value APIから取得した日時文字列 (dateTime, dateなど)。
* @param string $timezone 基準とするタイムゾーン。
* @return ?string 相対時間の文字列。変換できない場合はnull。
*/
function getRelativeTime(?string $value, string $timezone = 'Asia/Tokyo'): ?string
{
$dateObj = parseSpiralDateTime($value, 'dateTime'); // date型でもdateTimeとしてパース試行
if ($dateObj === null) {
$dateObj = parseSpiralDateTime($value, 'date');
}
if ($dateObj === null) {
return null;
}
$now = new DateTimeImmutable('now', new DateTimeZone($timezone));
$diff = $now->diff($dateObj);
$isPast = $diff->invert === 1;
$unit = $isPast ? '前' : '後';
if ($diff->y > 0) return $diff->y . '年' . $unit;
if ($diff->m > 0) return $diff->m . 'ヶ月' . $unit;
if ($diff->d > 0) return $diff->d . '日' . $unit;
if ($diff->h > 0) return $diff->h . '時間' . $unit;
if ($diff->i > 0) return $diff->i . '分' . $unit;
return 'たった今';
}
/**
* 西暦の日付を和暦(元号)形式の文字列に変換します。
*
* @param ?string $value APIから取得した日付文字列 (date, dateTime)。
* @return ?string 和暦の日付文字列。変換できない場合はnull。
*/
function formatWithJapaneseEra(?string $value): ?string
{
$dateObj = parseSpiralDateTime($value, 'date');
if ($dateObj === null) {
$dateObj = parseSpiralDateTime($value, 'dateTime');
}
if ($dateObj === null) {
return null;
}
$eras = [
['name' => '令和', 'start_date' => '2019-05-01'],
['name' => '平成', 'start_date' => '1989-01-08'],
['name' => '昭和', 'start_date' => '1926-12-25'],
['name' => '大正', 'start_date' => '1912-07-30'],
['name' => '明治', 'start_date' => '1868-01-25'], // グレゴリオ暦での明治開始日に近似
];
$year = (int)$dateObj->format('Y');
$month = (int)$dateObj->format('m');
$day = (int)$dateObj->format('d');
foreach ($eras as $era) {
$eraStartDate = new DateTimeImmutable($era['start_date']);
if ($dateObj >= $eraStartDate) {
$eraYear = $year - (int)$eraStartDate->format('Y') + 1;
$eraYearStr = ($eraYear === 1) ? '元' : (string)$eraYear;
return sprintf('%s%s年%d月%d日', $era['name'], $eraYearStr, $month, $day);
}
}
return $dateObj->format('Y年m月d日'); // どの元号にも当てはまらない場合
}
/**
* 指定された日付が週末(土曜日または日曜日)かどうかを判定します。
*
* @param ?DateTimeImmutable $dateObj 判定する日付オブジェクト。
* @return bool 週末であればtrue、そうでなければfalse。
*/
function isWeekend(?DateTimeImmutable $dateObj): bool
{
if ($dateObj === null) {
return false;
}
$dayOfWeek = (int)$dateObj->format('w'); // 0 (日) から 6 (土)
return ($dayOfWeek === 0 || $dayOfWeek === 6);
}
/**
* SPIRAL APIから取得した日付・時刻形式の文字列を DateTimeImmutable オブジェクトに変換します。
*
* @param ?string $value APIから取得した日付・時刻文字列。nullの場合はnullを返します。
* @param string $type フィールドタイプ ('date', 'monthDay', 'time', 'dateTime')。
* @return ?DateTimeImmutable 変換されたDateTimeImmutableオブジェクト。変換に失敗した場合はnullを返します。
*/
function parseSpiralDateTime(?string $value, string $type): ?DateTimeImmutable
{
if ($value === null || $value === '') {
return null;
}
try {
// スラッシュをハイフンに統一して扱いやすくする
$normalizedValue = str_replace('/', '-', $value);
switch ($type) {
case 'date':
// 例: '2016-01-01', '2016-1-1'
return new DateTimeImmutable($normalizedValue);
case 'monthDay':
// 例: '01-01', '1-1'
// 年がないため、比較などのために現在の年を補う
return new DateTimeImmutable(date('Y') . '-' . $normalizedValue);
case 'time':
// 例: '01:01:01', '1:1:1'
return new DateTimeImmutable($normalizedValue);
case 'dateTime':
// 例: '2016-01-01T12:00:00+09:00'
return new DateTimeImmutable($normalizedValue);
default:
return null;
}
} catch (Exception $e) {
// パースに失敗した場合はnullを返す
return null;
}
}
使い方
1. フィールド名の設定
まず、APIでレコードを取得するPHPスクリプトの上部に、以下のような設定エリアを設けます。
ご自身のデータベースで使っている日付・時刻フィールドの識別名を、それぞれ定数に設定してください。
//------------------------------
// フィールド名設定
//------------------------------
// ご自身のDBのフィールド識別名に合わせて書き換えてください
define("DATE_FIELD", "date"); //日付フィールド
define("DATETIME_FIELD", "dateTime"); //日時フィールド
define("MONTHDAY_FIELD", "monthDay"); //月日フィールド
define("TIME_FIELD", "time"); //時刻フィールド
// 作成日時はシステムフィールドのため、通常は '_createdAt' のままです
define("CREATED_AT_FIELD", "_createdAt");
2. 関数の呼び出し
APIから取得したレコードリストをループ処理し、中で各関数を呼び出します。
以下は、APIのレスポンスが
$resultRecordListSelectに格納されている場合のサンプルコードです。
//------------------------------
// お役立ち関数の利用例
//------------------------------
echo "<pre>";
echo "--- APIレスポンスをループ処理して日付をフォーマットする例 ---\n";
if (isset($resultRecordListSelect['items']) && is_array($resultRecordListSelect['items'])) {
foreach ($resultRecordListSelect['items'] as $record) {
echo "\n--- Record ID: " . $record['_id'] . " ---\n";
// --- 基本的なフォーマット ---
$dateWithDay = formatSpiralDateTime($record[DATE_FIELD], 'date', 'Y/m/d (w_jp)');
echo "日付 (曜日付き) : " . $dateWithDay . "\n";
$formattedMonthDay = formatSpiralDateTime($record[MONTHDAY_FIELD], 'monthDay', 'm月d日');
echo "月日 : " . $formattedMonthDay . "\n";
$formattedTime = formatSpiralDateTime($record[TIME_FIELD], 'time', 'H時i分s秒');
echo "時刻 : " . $formattedTime . "\n";
// --- 12時間/24時間表記と日本語時刻 ---
$dateTime24h = formatSpiralDateTime($record[DATETIME_FIELD], 'dateTime', 'Y年m月d日 H時i分s秒');
echo "日時 (24時間表記) : " . $dateTime24h . "\n";
$dateTime12h = formatSpiralDateTime($record[DATETIME_FIELD], 'dateTime', 'Y年m月d日 g_jp g時i分');
echo "日時 (12時間表記) : " . $dateTime12h . "\n";
// --- 和暦表示 ---
$japaneseEra = formatWithJapaneseEra($record[DATE_FIELD]);
echo "日付 (和暦) : " . $japaneseEra . "\n";
// --- 週末判定 ---
$dateObj = parseSpiralDateTime($record[DATE_FIELD], 'date');
$weekendStatus = isWeekend($dateObj) ? '週末です' : '平日です';
echo "週末判定 : " . $weekendStatus . "\n";
// --- 相対時間 ---
$createdRelative = getRelativeTime($record[CREATED_AT_FIELD]);
echo "作成日時 (相対) : " . $createdRelative . "\n";
}
} else {
echo "レコードが見つかりませんでした。";
}
echo "</pre>";
実行結果
上記のサンプルコードを実行すると、以下のような結果が出力されます。
--- Record ID: 3 ---
日付 (曜日付き) : 2025/10/09 (木)
月日 : 08月20日
時刻 : 12時30分00秒
日時 (24時間表記) : 2017年10月06日 02時00分00秒
日時 (12時間表記) : 2017年10月06日 午前 2時00分
日付 (和暦) : 令和7年10月9日
週末判定 : 平日です
作成日時 (相対) : ◯◯分前
--- Record ID: 2 ---
日付 (曜日付き) : 2025/10/02 (木)
月日 : 05月21日
時刻 : 01時30分00秒
日時 (24時間表記) : 2025年10月10日 00時30分00秒
日時 (12時間表記) : 2025年10月10日 午前 12時30分
日付 (和暦) : 令和7年10月2日
週末判定 : 平日です
作成日時 (相対) : ◯◯分前
サンプルコード全文
<?php
//------------------------------
// 設定値
//------------------------------
define("API_URL", "https://api.spiral-platform.com/v1");
define("API_KEY", "APIキー");
define("APP_ROLE", "アプリロール識別名");
define("DB_ID", "DBID");
define("APP_ID", "アプリID");
//------------------------------
// フィールド名設定
//------------------------------
// ご自身のDBのフィールド識別名に合わせて書き換えてください
define("DATE_FIELD", "date"); //日付フィールド
define("DATETIME_FIELD", "dateTime"); //日時フィールド
define("MONTHDAY_FIELD", "monthDay"); //月日フィールド
define("TIME_FIELD", "time"); //時刻フィールド
// 作成日時はシステムフィールドのため、通常は '_createdAt' のままです
define("CREATED_AT_FIELD", "_createdAt");
//------------------------------
// API実行
//------------------------------
$commonBase = CommonBase::getInstance();
$resultRecordListSelect = $commonBase->apiCurlAction("GET", "/apps/". APP_ID. "/dbs/". DB_ID. "/records");
//------------------------------
// 共通モジュール
//------------------------------
class CommonBase {
/**
* シングルトンインスタンス
* @var UserManager
*/
protected static $singleton;
public function __construct() {
if (self::$singleton) {
throw new Exception('must be singleton');
}
self::$singleton = $this;
}
/**
* シングルトンインスタンスを返す
* @return UserManager
*/
public static function getInstance() {
if (!self::$singleton) {
return new CommonBase();
} else {
return self::$singleton;
}
}
/**
* V2用 API送信ロジック
* @return Result
*/
function apiCurlAction($method, $addUrlPass, $data = null, $multiPart = null, $jsonDecode = null) {
$header = array(
"Authorization:Bearer ". API_KEY,
"X-Spiral-Api-Version: 1.1",
);
if($multiPart) {
$header = array_merge($header, array($multiPart));
} else {
$header = array_merge($header, array("Content-Type:application/json"));
}
if(APP_ROLE){
$header = array_merge($header, array("X-Spiral-App-Role: ".APP_ROLE));
}
// curl
$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_URL, API_URL. $addUrlPass);
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
if ($method == "POST") {
if ($multiPart) {
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
} else {
curl_setopt($curl, CURLOPT_POSTFIELDS , json_encode($data));
}
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
}
if ($method == "PATCH") {
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
}
if ($method == "DELETE") {
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
}
$response = curl_exec($curl);
if (curl_errno($curl)) echo curl_error($curl);
curl_close($curl);
if($jsonDecode){
return $response;
}else{
return json_decode($response, true);
}
}
}
//------------------------------
// 日付・時刻お役立ち関数
//------------------------------
/**
* SPIRAL APIから取得した日付文字列を、指定したフォーマットの文字列に変換します。
* 曜日の日本語表示など、よく使う形式を簡単に呼び出せます。
*
* @param ?string $value APIから取得した日付・時刻文字列。
* @param string $type フィールドタイプ ('date', 'monthDay', 'time', 'dateTime')。
* @param string $format 出力フォーマット。'Y-m-d', 'Y年m月d日', 'Y/m/d (w_jp)' など。
* 'w_jp' を含めると、その部分が日本語の曜日に置き換わります (例: 日, 月)。
* @return ?string フォーマットされた日付文字列。変換できない場合はnullを返します。
*/
function formatSpiralDateTime(?string $value, string $type, string $format, string $timezone = 'Asia/Tokyo'): ?string
{
$dateObj = parseSpiralDateTime($value, $type);
if ($dateObj === null) {
return null;
}
// dateTime型の場合は、指定されたタイムゾーンに変換
if ($type === 'dateTime') {
$dateObj = $dateObj->setTimezone(new DateTimeZone($timezone));
}
// 午前/午後付き12時間表記
if (strpos($format, 'g_jp') !== false) {
$am_pm = ((int)$dateObj->format('G') < 12) ? '午前' : '午後';
$format = str_replace('g_jp', $am_pm, $format);
}
// フォーマットに 'w_jp' が含まれている場合、日本語の曜日に置換する
if (strpos($format, 'w_jp') !== false) {
$week = ['日', '月', '火', '水', '木', '金', '土'];
$dayOfWeek = $week[(int)$dateObj->format('w')];
$format = str_replace('w_jp', $dayOfWeek, $format);
}
return $dateObj->format($format);
}
/**
* 指定された日時文字列と現在時刻との差を「〇分前」「〇日後」のような相対時間で返します。
*
* @param ?string $value APIから取得した日時文字列 (dateTime, dateなど)。
* @param string $timezone 基準とするタイムゾーン。
* @return ?string 相対時間の文字列。変換できない場合はnull。
*/
function getRelativeTime(?string $value, string $timezone = 'Asia/Tokyo'): ?string
{
$dateObj = parseSpiralDateTime($value, 'dateTime'); // date型でもdateTimeとしてパース試行
if ($dateObj === null) {
$dateObj = parseSpiralDateTime($value, 'date');
}
if ($dateObj === null) {
return null;
}
$now = new DateTimeImmutable('now', new DateTimeZone($timezone));
$diff = $now->diff($dateObj);
$isPast = $diff->invert === 1;
$unit = $isPast ? '前' : '後';
if ($diff->y > 0) return $diff->y . '年' . $unit;
if ($diff->m > 0) return $diff->m . 'ヶ月' . $unit;
if ($diff->d > 0) return $diff->d . '日' . $unit;
if ($diff->h > 0) return $diff->h . '時間' . $unit;
if ($diff->i > 0) return $diff->i . '分' . $unit;
return 'たった今';
}
/**
* 西暦の日付を和暦(元号)形式の文字列に変換します。
*
* @param ?string $value APIから取得した日付文字列 (date, dateTime)。
* @return ?string 和暦の日付文字列。変換できない場合はnull。
*/
function formatWithJapaneseEra(?string $value): ?string
{
$dateObj = parseSpiralDateTime($value, 'date');
if ($dateObj === null) {
$dateObj = parseSpiralDateTime($value, 'dateTime');
}
if ($dateObj === null) {
return null;
}
$eras = [
['name' => '令和', 'start_date' => '2019-05-01'],
['name' => '平成', 'start_date' => '1989-01-08'],
['name' => '昭和', 'start_date' => '1926-12-25'],
['name' => '大正', 'start_date' => '1912-07-30'],
['name' => '明治', 'start_date' => '1868-01-25'], // グレゴリオ暦での明治開始日に近似
];
$year = (int)$dateObj->format('Y');
$month = (int)$dateObj->format('m');
$day = (int)$dateObj->format('d');
foreach ($eras as $era) {
$eraStartDate = new DateTimeImmutable($era['start_date']);
if ($dateObj >= $eraStartDate) {
$eraYear = $year - (int)$eraStartDate->format('Y') + 1;
$eraYearStr = ($eraYear === 1) ? '元' : (string)$eraYear;
return sprintf('%s%s年%d月%d日', $era['name'], $eraYearStr, $month, $day);
}
}
return $dateObj->format('Y年m月d日'); // どの元号にも当てはまらない場合
}
/**
* 指定された日付が週末(土曜日または日曜日)かどうかを判定します。
*
* @param ?DateTimeImmutable $dateObj 判定する日付オブジェクト。
* @return bool 週末であればtrue、そうでなければfalse。
*/
function isWeekend(?DateTimeImmutable $dateObj): bool
{
if ($dateObj === null) {
return false;
}
$dayOfWeek = (int)$dateObj->format('w'); // 0 (日) から 6 (土)
return ($dayOfWeek === 0 || $dayOfWeek === 6);
}
/**
* SPIRAL APIから取得した日付・時刻形式の文字列を DateTimeImmutable オブジェクトに変換します。
*
* @param ?string $value APIから取得した日付・時刻文字列。nullの場合はnullを返します。
* @param string $type フィールドタイプ ('date', 'monthDay', 'time', 'dateTime')。
* @return ?DateTimeImmutable 変換されたDateTimeImmutableオブジェクト。変換に失敗した場合はnullを返します。
*/
function parseSpiralDateTime(?string $value, string $type): ?DateTimeImmutable
{
if ($value === null || $value === '') {
return null;
}
try {
// スラッシュをハイフンに統一して扱いやすくする
$normalizedValue = str_replace('/', '-', $value);
switch ($type) {
case 'date':
// 例: '2016-01-01', '2016-1-1'
return new DateTimeImmutable($normalizedValue);
case 'monthDay':
// 例: '01-01', '1-1'
// 年がないため、比較などのために現在の年を補う
return new DateTimeImmutable(date('Y') . '-' . $normalizedValue);
case 'time':
// 例: '01:01:01', '1:1:1'
return new DateTimeImmutable($normalizedValue);
case 'dateTime':
// 例: '2016-01-01T12:00:00+09:00'
return new DateTimeImmutable($normalizedValue);
default:
return null;
}
} catch (Exception $e) {
// パースに失敗した場合はnullを返す
return null;
}
}
//------------------------------
// お役立ち関数の利用例
//------------------------------
echo "<pre>";
echo "--- APIレスポンスをループ処理して日付をフォーマットする例 ---\n";
if (isset($resultRecordListSelect['items']) && is_array($resultRecordListSelect['items'])) {
foreach ($resultRecordListSelect['items'] as $record) {
echo "\n--- Record ID: " . $record['_id'] . " ---\n";
// --- 基本的なフォーマット ---
$dateWithDay = formatSpiralDateTime($record[DATE_FIELD], 'date', 'Y/m/d (w_jp)');
echo "日付 (曜日付き) : " . $dateWithDay . "\n";
$formattedMonthDay = formatSpiralDateTime($record[MONTHDAY_FIELD], 'monthDay', 'm月d日');
echo "月日 : " . $formattedMonthDay . "\n";
$formattedTime = formatSpiralDateTime($record[TIME_FIELD], 'time', 'H時i分s秒');
echo "時刻 : " . $formattedTime . "\n";
// --- 12時間/24時間表記と日本語時刻 ---
$dateTime24h = formatSpiralDateTime($record[DATETIME_FIELD], 'dateTime', 'Y年m月d日 H時i分s秒');
echo "日時 (24時間表記) : " . $dateTime24h . "\n";
$dateTime12h = formatSpiralDateTime($record[DATETIME_FIELD], 'dateTime', 'Y年m月d日 g_jp g時i分');
echo "日時 (12時間表記) : " . $dateTime12h . "\n";
// --- 和暦表示 ---
$japaneseEra = formatWithJapaneseEra($record[DATE_FIELD]);
echo "日付 (和暦) : " . $japaneseEra . "\n";
// --- 週末判定 ---
$dateObj = parseSpiralDateTime($record[DATE_FIELD], 'date');
$weekendStatus = isWeekend($dateObj) ? '週末です' : '平日です';
echo "週末判定 : " . $weekendStatus . "\n";
// --- 相対時間 ---
$createdRelative = getRelativeTime($record[CREATED_AT_FIELD]);
echo "作成日時 (相対) : " . $createdRelative . "\n";
}
} else {
echo "レコードが見つかりませんでした。";
}
echo "</pre>";
まとめ
これらの関数を組み合わせることで、複雑な日付処理をシンプルに記述でき、開発効率の向上が期待できます。
ぜひ、ご自身のプロジェクトに合わせてカスタマイズしてご活用ください。
不具合やご質問がある場合は、下記の「コンテンツに関しての要望はこちら」からご連絡ください。