site_bc\strftime
composer にあった site_bc\strftime がイマイチだったのでかなり前に自作したんだけど、公開してなかったので供養。
最近だと生成ツールに「strftime() と互換性のある関数作って」と言えば作ってくれそうだけど。
(ちょっと前に試したらイマイチだったけど、近年ならマシになってるかも)
<?php namespace site_bc; use Exception; function strftime($format, $ut=null) { if (STRFTIME::$FUNC) { return STRFTIME::conv_func($format, $ut); } $date_format = STRFTIME::conv_format($format); return date($date_format, $ut); } class STRFTIME { static $FUNC = true; static $FULL = true; const FORMAT = [ 'a' => 'D', 'b' => 'M', 'c' => ['D M j H:i:s Y', 'conv_c1'], 'd' => 'd', 'e' => ['j', 'conv_e1'], 'f' => '\f', 'g' => ['o', 'conv_g1'], 'h' => 'M', 'i' => '\i', 'j' => ['z', 'conv_j1'], 'k' => ['G', 'conv_k1'], 'l' => ['g', 'conv_l1'], 'm' => 'm', 'n' => "\n", 'o' => '\o', 'p' => 'A', 'q' => '\q', 'r' => 'h:i:s A', 's' => 'U', 't' => "\t", 'u' => 'N', 'v' => ['j-M-Y', 'conv_v1'], 'w' => 'w', 'x' => 'm/d/y', 'y' => 'y', 'z' => 'O', 'A' => 'l', 'B' => 'F', 'C' => ['', 'conv_c2'], 'D' => 'm/d/y', 'E' => '', # 特殊ケースあり 'F' => 'Y-m-d', 'G' => 'o', 'H' => 'H', 'I' => 'h', 'J' => '\J', 'K' => '\K', 'L' => '\L', 'M' => 'i', 'N' => '\N', 'O' => '', # 特殊ケースあり 'P' => '\P', 'Q' => '\Q', 'R' => 'H:i', 'S' => 's', 'T' => 'H:i:s', 'U' => ['W', 'conv_u2'], 'V' => 'W', 'W' => ['W', 'conv_w2'], 'X' => 'H:i:s', 'Y' => 'Y', 'Z' => 'T', '%' => '%', ]; static $search; static $replace; static $invalid; static function _mk_replace() { if (! isset(static::$search)) { static::$search = []; static::$replace = []; static::$invalid = ''; foreach (static::FORMAT as $f => $t) { static::$search[] = "%$f"; if (is_array($t)) { static::$replace[] = $t[0]; static::$invalid .= $f; } else { static::$replace[] = $t; } } } return [ static::$search, static::$replace, static::$invalid ]; } static function conv_format($format, $full=null) { if ($full === null) $full = static::$FULL; $format = preg_replace('/(?<![%])([a-zA-Z])/', '\\\\$1', $format);; $sr = static::_mk_replace(); if ($full) { if (preg_match("/(%[{$sr[2]}])/", $format, $m)) { throw new Exception("can't convert date format '{$m[1]}'"); } } return str_replace($sr[0], $sr[1], $format); } static function conv_func($format, $ut=null) { $ut ??= time(); $date_str = preg_replace_callback( '/[%]([a-zA-Z%])/', function ($m) use ($ut) { $conv = static::FORMAT[$m[1]]; if (is_array($conv)) { return static::{$conv[1]}($ut); } return date($conv, $ut); }, $format ); return $date_str; } static function conv_e1($ut) { return str_pad(idate('d', $ut), 2, ' ', STR_PAD_LEFT); } static function conv_g1($ut) { return substr( date('o', $ut), -2); } static function conv_c2($ut) { return (int)(idate('Y', $ut) / 100); } static function conv_k1($ut) { return str_pad(idate('H', $ut), 2, ' ', STR_PAD_LEFT); } static function conv_l1($ut) { return str_pad(idate('h', $ut), 2, ' ', STR_PAD_LEFT); } static function conv_j1($ut) { return str_pad((date('z', $ut) + 1), 3, '0', STR_PAD_LEFT); } static function conv_c1($ut) { $day = static::conv_e1($ut); return date("D M $day H:i:s Y", $ut); } static function conv_v1($ut) { $day = static::conv_e1($ut); return date("$day-M-Y", $ut); } static function calc_weeknum($ut, $target) { $year = idate('Y', $ut); $ut_d1 = mktime(0, 0, 0, 1, 1, $year); $d1_week = idate('w', $ut_d1); $next = (7 - $d1_week + $target) % 7; $ut_ds = mktime(0, 0, 0, 1, $next + 1, $year); $dd = date('z', $ut) - date('z', $ut_ds); $weeknum = floor($dd / 7) + 1; return str_pad($weeknum, 2, '0', STR_PAD_LEFT); } static function conv_u2($ut) { return static::calc_weeknum($ut, 0); } static function conv_w2($ut) { return static::calc_weeknum($ut, 1); } }