Slide 1

Slide 1 text

PHPで使える日時の表現と、 その知り方 フロントエンド・PHPカンファレンス北海道2026 Hideki Kinjyo GitHub: o0h / X: @o0h_ [公開用] v1.2.1

Slide 2

Slide 2 text

Slide 3

Slide 3 text

Slide 4

Slide 4 text

Slide 5

Slide 5 text

Slide 6

Slide 6 text

Slide 7

Slide 7 text

キーワード指定にも 対応している 

Slide 8

Slide 8 text

Slide 9

Slide 9 text

Slide 10

Slide 10 text

Slide 11

Slide 11 text

相対表記も使える 

Slide 12

Slide 12 text

Slide 13

Slide 13 text

Slide 14

Slide 14 text

色々と組み合わせることもできる 

Slide 15

Slide 15 text

Slide 16

Slide 16 text

Slide 17

Slide 17 text

Slide 18

Slide 18 text

Slide 19

Slide 19 text

Slide 20

Slide 20 text

対応している表現が多い (大変) 

Slide 21

Slide 21 text

マニュアルを見てみよう (http://php.net/datetime.formats) 

Slide 22

Slide 22 text

「サポートする日付と時刻の書式」 

Slide 23

Slide 23 text

「サポートする日付と時刻の書式」  丁寧で充実した説明

Slide 24

Slide 24 text

「サポートする日付と時刻の書式」  情報が盛り沢山🤤 (document.body.innerText.length // 15404)

Slide 25

Slide 25 text

暗記が大変だ 

Slide 26

Slide 26 text

暗記が大変だ 仕組みを知ろう 

Slide 27

Slide 27 text

LTタイトルを大発表! 

Slide 28

Slide 28 text

自己紹介 • 金城秀樹 / きんじょうひでき • GitHub: @o0h / 𝕏 : @o0h_ • アイコンは美味しい鮭親子丼の写真です • 東京でPHPを使っています • 最近はPodcastをやっています • ハッシュタグ: #readlinefm 

Slide 29

Slide 29 text

やること PHPのソースコードにある ext/date/lib/parse_date.re を開いてください 

Slide 30

Slide 30 text

PHPのソースコードにある ext/date/lib/parse_date.re を開いてください やること .re  re2cというツールの ファイル

Slide 31

Slide 31 text

re2c? 正規表現でマッチした字句に Cの処理を適用する 

Slide 32

Slide 32 text

re2c? 正規表現でマッチした字句に Cの処理を適用する 

Slide 33

Slide 33 text

 正規表現のパターン

Slide 34

Slide 34 text

/*!re2c year2 = [0-9]{2}; year4 = [0-9]{4}; */  正規表現のパターン

Slide 35

Slide 35 text

/*!re2c year2 = [0-9]{2}; year4 = [0-9]{4}; */  00 12 88

Slide 36

Slide 36 text

/*!re2c year2 = [0-9]{2}; year4 = [0-9]{4}; */  0001 2026 9999

Slide 37

Slide 37 text

/*!re2c monthlz = "0"[0-9]|"1"[0-2]; daylz = "0"[0-9]|[1-2][0-9]|"3"[01]; */  正規表現のパターン

Slide 38

Slide 38 text

/*!re2c monthlz = "0"[0-9]|"1"[0-2]; daylz = "0"[0-9]|[1-2][0-9]|"3"[01]; */  00 12 09 10 30 31

Slide 39

Slide 39 text

/*!re2c datenocolon = year4 monthlz daylz; */  定義したパターンを 再利用する

Slide 40

Slide 40 text

/*!re2c datenocolon = year4 monthlz daylz; */  21120903 20260606

Slide 41

Slide 41 text

re2c? 正規表現でマッチした字句に Cの処理を適用する 

Slide 42

Slide 42 text

 Cの処理

Slide 43

Slide 43 text

datenocolon { s->time->y = timelib_get_nr(&ptr,4); s->time->m = timelib_get_nr(&ptr,2); s->time->d = timelib_get_nr(&ptr,2); }  大事な部分だけ 見てみる

Slide 44

Slide 44 text

datenocolon { s->time->y = timelib_get_nr(&ptr,4); s->time->m = timelib_get_nr(&ptr,2); s->time->d = timelib_get_nr(&ptr,2); }  ルール

Slide 45

Slide 45 text

datenocolon { s->time->y = timelib_get_nr(&ptr,4); s->time->m = timelib_get_nr(&ptr,2); s->time->d = timelib_get_nr(&ptr,2); }  アクション

Slide 46

Slide 46 text

datenocolon { s->time->y = timelib_get_nr(&ptr,4); s->time->m = timelib_get_nr(&ptr,2); s->time->d = timelib_get_nr(&ptr,2); }  数字だけ4文字抜き出す

Slide 47

Slide 47 text

datenocolon { s->time->y = timelib_get_nr(&ptr,4); s->time->m = timelib_get_nr(&ptr,2); s->time->d = timelib_get_nr(&ptr,2); }  「time」の「y」に入れる

Slide 48

Slide 48 text

datenocolon { s->time->y = timelib_get_nr(&ptr,4); s->time->m = timelib_get_nr(&ptr,2); s->time->d = timelib_get_nr(&ptr,2); }  「time」の「m」に 「次の数字2文字」を入れる

Slide 49

Slide 49 text

datenocolon { s->time->y = timelib_get_nr(&ptr,4); s->time->m = timelib_get_nr(&ptr,2); s->time->d = timelib_get_nr(&ptr,2); }  「time」の「d」に 「次の数字2文字」を入れる

Slide 50

Slide 50 text

parse_date.reがやっていること  つまり、PHPは 「文字を解釈して日時にする」ために

Slide 51

Slide 51 text

parse_date.reがやっていること  1. 字句パターンを定義して 2. それに対応する「アクション」内で 3. `time`の中身をいじっている

Slide 52

Slide 52 text

色々な例を見て見る 

Slide 53

Slide 53 text

例1: 単純なやつ 

Slide 54

Slide 54 text

Slide 55

Slide 55 text

'noon' { DEBUG_OUTPUT("noon"); TIMELIB_INIT; TIMELIB_UNHAVE_TIME(); TIMELIB_HAVE_TIME(); s->time->h = 12; TIMELIB_DEINIT; return TIMELIB_RELATIVE; } 

Slide 56

Slide 56 text

'noon' { DEBUG_OUTPUT("noon"); TIMELIB_INIT; TIMELIB_UNHAVE_TIME(); TIMELIB_HAVE_TIME(); s->time->h = 12; TIMELIB_DEINIT; return TIMELIB_RELATIVE; }  'noon'

Slide 57

Slide 57 text

'noon' { DEBUG_OUTPUT("noon"); TIMELIB_INIT; TIMELIB_UNHAVE_TIME(); TIMELIB_HAVE_TIME(); s->time->h = 12; TIMELIB_DEINIT; return TIMELIB_RELATIVE; }  s->time->h = 12;

Slide 58

Slide 58 text

Slide 59

Slide 59 text

monthfull = 'january'|'february'| 'march'|'april'|'may'| 'june'|'july'|'august'| 'september'|'october'| 'november'|'december'; 

Slide 60

Slide 60 text

monthfull | monthabbr { DEBUG_OUTPUT("monthtext"); TIMELIB_INIT; TIMELIB_HAVE_DATE(); s->time->m = timelib_lookup_month(&ptr); TIMELIB_DEINIT; return TIMELIB_DATE_TEXT; }  s->time->m = timelib_lookup_month(&ptr); mouthfull

Slide 61

Slide 61 text

Slide 62

Slide 62 text

monthtext = monthfull| monthabbr| monthroman; 

Slide 63

Slide 63 text

datenoyear = monthtext ([ .\t-])* day ([,.stndrh\t ]+|[\000]); 

Slide 64

Slide 64 text

datetextual | datenoyear { int length = 0; DEBUG_OUTPUT("datetextual | datenoyear"); TIMELIB_INIT; TIMELIB_HAVE_DATE(); s->time->m = timelib_get_month(&ptr); s->time->d = timelib_get_nr(&ptr, 2); s->time->y = timelib_get_nr_ex(&ptr, 4, &length); TIMELIB_PROCESS_YEAR(s->time->y, length); TIMELIB_DEINIT; return TIMELIB_DATE_TEXT; } 

Slide 65

Slide 65 text

datetextual | datenoyear { int length = 0; DEBUG_OUTPUT("datetextual | datenoyear"); TIMELIB_INIT; TIMELIB_HAVE_DATE(); s->time->m = timelib_get_month(&ptr); s->time->d = timelib_get_nr(&ptr, 2); s->time->y = timelib_get_nr_ex(&ptr, 4, &length); TIMELIB_PROCESS_YEAR(s->time->y, length); TIMELIB_DEINIT; return TIMELIB_DATE_TEXT; }  datenoyear s->time->m = ... s->time->d = ...

Slide 66

Slide 66 text

Slide 67

Slide 67 text

Slide 68

Slide 68 text

'now' { DEBUG_OUTPUT("now"); TIMELIB_INIT; TIMELIB_DEINIT; return TIMELIB_RELATIVE; }  何も値をいじらない = 現在日時のまま

Slide 69

Slide 69 text

例2: 相対指定 

Slide 70

Slide 70 text

Slide 71

Slide 71 text

'yesterday' { DEBUG_OUTPUT("yesterday"); TIMELIB_INIT; TIMELIB_HAVE_RELATIVE(); TIMELIB_UNHAVE_TIME(); s->time->relative.d = -1; TIMELIB_DEINIT; return TIMELIB_RELATIVE; }  ※ 画面上の都合で、内容を一部改修しています

Slide 72

Slide 72 text

'yesterday' { DEBUG_OUTPUT("yesterday"); TIMELIB_INIT; TIMELIB_HAVE_RELATIVE(); TIMELIB_UNHAVE_TIME(); s->time->relative.d = -1; TIMELIB_DEINIT; return TIMELIB_RELATIVE; }  s->time->relative.d = -1; 'yesterday' ※ 画面上の都合で、内容を一部改修しています

Slide 73

Slide 73 text

Slide 74

Slide 74 text

relative = relnumber reltextunit; 

Slide 75

Slide 75 text

reltextunit = 'ms' | 'µs' | (('msec'|'millisecond'|'µsec'|'mi crosecond'|'usec'|'sec'|'second'| 'min'|'minute'|'hour'|'day'|'fort night'|'forthnight'|'month'|'year ') 's'?) | 'weeks' | daytext; 

Slide 76

Slide 76 text

time->relative.y += 1;

Slide 77

Slide 77 text

time->relative.m += 2;

Slide 78

Slide 78 text

time->relative.d += 3;

Slide 79

Slide 79 text

time->relative.h += 4;

Slide 80

Slide 80 text

time->relative.i += 5;

Slide 81

Slide 81 text

time->relative.s += 6;

Slide 82

Slide 82 text

例3: 細かくて分かりにくいやつ 

Slide 83

Slide 83 text

6月6日の0時0分0秒

Slide 84

Slide 84 text

Slide 85

Slide 85 text

time->m = 6

Slide 86

Slide 86 text

Slide 87

Slide 87 text

Slide 88

Slide 88 text

time->relative.d += 6;

Slide 89

Slide 89 text

例4: 複雑なやつ 

Slide 90

Slide 90 text

Slide 91

Slide 91 text

Slide 92

Slide 92 text

Slide 93

Slide 93 text

Slide 94

Slide 94 text

Slide 95

Slide 95 text

Slide 96

Slide 96 text

Slide 97

Slide 97 text

Slide 98

Slide 98 text

Slide 99

Slide 99 text

time->relative.d += 3

Slide 100

Slide 100 text

Slide 101

Slide 101 text

time->relative.h += 99

Slide 102

Slide 102 text

Slide 103

Slide 103 text

Slide 104

Slide 104 text

time->relative.i += 3

Slide 105

Slide 105 text

time->y = 2021

Slide 106

Slide 106 text

time->relative.d += (-1 * 7) s->time->relative.weekday = 1;

Slide 107

Slide 107 text

time->z = 18.00 * 60 * 60

Slide 108

Slide 108 text

Slide 109

Slide 109 text

まとめ 

Slide 110

Slide 110 text

今、PHPの日時について 完全に理解しかけている 状態です 

Slide 111

Slide 111 text

① 指定した数字やフレーズが 

Slide 112

Slide 112 text

② 日時を構成する「どれかの要素」に 

Slide 113

Slide 113 text

③ 絶対値 もしくは 相対値 をセットして 

Slide 114

Slide 114 text

④ それらの値を、丸っと処理して 日時の出来上がり! 

Slide 115

Slide 115 text

困ったら parse_date.re 

Slide 116

Slide 116 text

という話をしました 〜めでたし めでたし〜 

Slide 117

Slide 117 text

マニュアルを見ても、 「複雑すぎて分からん」 「組み合わせるとどうなるの」 になる場合でも 

Slide 118

Slide 118 text

実装を見ると 「仕組み」が見えてきて 便利 

Slide 119

Slide 119 text

だとしても 

Slide 120

Slide 120 text

標準的な表現を使って欲しいと思いました (YYYY-MM-DDとか) 

Slide 121

Slide 121 text

おしまい! お付き合いいただき ありがとうございました!!