1: <?php
2: /*
3: * Copyright (c) 2014 @trashtoy
4: * https://github.com/trashtoy/
5: *
6: * Permission is hereby granted, free of charge, to any person obtaining a copy of
7: * this software and associated documentation files (the "Software"), to deal in
8: * the Software without restriction, including without limitation the rights to use,
9: * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
10: * Software, and to permit persons to whom the Software is furnished to do so,
11: * subject to the following conditions:
12: *
13: * The above copyright notice and this permission notice shall be included in all
14: * copies or substantial portions of the Software.
15: *
16: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18: * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19: * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20: * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21: * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22: */
23: /**
24: * PHP class file.
25: * @auhtor trashtoy
26: * @since 2.0.0
27: */
28: namespace Peach\DT;
29: use Peach\Util\Map;
30: use Peach\Util\ArrayMap;
31:
32: /**
33: * TIMESTAMP 型の時間オブジェクトです.
34: * このクラスは年・月・日・時・分・秒のフィールドをサポートします.
35: */
36: class Timestamp extends Datetime
37: {
38: /**
39: * 秒を表す整数です.
40: * @var int
41: */
42: protected $second = 0;
43:
44: /**
45: * 実行時の Timestamp オブジェクトを返します.
46: *
47: * @param Clock $clock 現在時刻を取得するための Clock オブジェクト
48: * @return Timestamp 現在時刻をあらわす Timestamp
49: */
50: public static function now(Clock $clock = null)
51: {
52: if ($clock === null) {
53: return self::now(DefaultClock::getInstance());
54: }
55:
56: return $clock->getTimestamp();
57: }
58:
59: /**
60: * 指定されたテキストを解析して Timestamp オブジェクトに変換します.
61: * $format が指定されていない場合は {@link W3cDatetimeFormat::getInstance}
62: * を使って解析を行います.
63: * ("YYYY-MM-DD hh:mm:ss" 形式の文字列を受理します.
64: * 日付と時刻のセパレータは, 数字以外の ASCII 1 文字であれば何でも構いません.)
65: *
66: * @param string $text 変換対象の文字列
67: * @param Format $format 変換に使用するフォーマット
68: * @return Timestamp 変換結果
69: */
70: public static function parse($text, Format $format = null)
71: {
72: if (!isset($format)) {
73: $format = W3cDatetimeFormat::getInstance();
74: }
75: return $format->parseTimestamp($text);
76: }
77:
78: /**
79: * 与えられた時刻を表現する Timestamp オブジェクトを構築します.
80: *
81: * @param int $year 年
82: * @param int $month 月
83: * @param int $date 日
84: * @param int $hour 時
85: * @param int $min 分
86: * @param int $sec 秒
87: */
88: public function __construct($year, $month, $date, $hour, $min, $sec)
89: {
90: $fields = new ArrayMap();
91: $fields->put(self::$YEAR, intval($year));
92: $fields->put(self::$MONTH, intval($month));
93: $fields->put(self::$DATE, intval($date));
94: $fields->put(self::$HOUR, intval($hour));
95: $fields->put(self::$MINUTE, intval($min));
96: $fields->put(self::$SECOND, intval($sec));
97: $this->init($fields);
98: }
99:
100: /**
101: * このオブジェクトの型 {@link Time::TYPE_TIMESTAMP} を返します.
102: * @return int Time::TYPE_TIMESTAMP
103: */
104: public function getType()
105: {
106: return self::TYPE_TIMESTAMP;
107: }
108:
109: /**
110: * @ignore
111: */
112: protected function init(Map $fields)
113: {
114: parent::init($fields);
115: $this->second = $fields->get(self::$SECOND);
116: }
117:
118: /**
119: * この時間と指定された時間を比較します.
120: *
121: * @param Time $time 比較対象の時間
122: * @return int この時間のほうが過去の場合は負の値, 未来の場合は正の値, それ以外は 0
123: * @ignore
124: */
125: protected function compareFields(Time $time)
126: {
127: $c = parent::compareFields($time);
128: if (!isset($c) || $c != 0) {
129: return $c;
130: }
131: $className = __CLASS__;
132: if ($time instanceof $className) {
133: return $this->second - $time->second;
134: } else {
135: $s = $time->get("second");
136: return ($s !== $this->second) ? $this->second - $s : 0;
137: }
138: }
139:
140: /**
141: * 時刻の不整合を調整します.
142: * @ignore
143: */
144: protected function adjust(Map $fields)
145: {
146: parent::adjust($fields);
147: $adjuster = $this->getAdjuster();
148: $second = $fields->get(self::$SECOND);
149: if ($second < 0) {
150: $adjuster->moveDown($fields);
151: } else if (59 < $second) {
152: $adjuster->moveUp($fields);
153: } else {
154: return;
155: }
156:
157: $this->adjust($fields);
158: }
159:
160: /**
161: * (non-PHPdoc)
162: * @see Time::newInstance()
163: * @ignore
164: */
165: protected function newInstance(Map $fields)
166: {
167: $year = $fields->get(self::$YEAR);
168: $month = $fields->get(self::$MONTH);
169: $date = $fields->get(self::$DATE);
170: $hour = $fields->get(self::$HOUR);
171: $min = $fields->get(self::$MINUTE);
172: $sec = $fields->get(self::$SECOND);
173: return new self($year, $month, $date, $hour, $min, $sec);
174: }
175:
176: /**
177: * @ignore
178: */
179: protected function handleFormat(Format $format)
180: {
181: return $format->formatTimestamp($this);
182: }
183:
184: /**
185: * このオブジェクトの時刻部分の文字列を "hh:mm:ss" 形式で返します.
186: * @return string "hh:mm:ss" 形式の文字列
187: */
188: public function formatTime()
189: {
190: $format = parent::formatTime();
191: $sec = str_pad($this->second, 2, '0', STR_PAD_LEFT);
192: return $format . ":" . $sec;
193: }
194:
195: /**
196: * このオブジェクトを Timestamp 型にキャストします.
197: * 返り値はこのオブジェクトのクローンです.
198: *
199: * @return Timestamp このオブジェクトの Timestamp 表現
200: */
201: public function toTimestamp()
202: {
203: return new Timestamp($this->year, $this->month, $this->date, $this->hour, $this->minute, $this->second);
204: }
205:
206: /**
207: * このクラスのフィールドを調整するための FieldAdjuster を返します.
208: * @return FieldAdjuster
209: * @codeCoverageIgnore
210: */
211: private function getAdjuster()
212: {
213: static $adjuster = null;
214: if ($adjuster === null) {
215: $adjuster = new FieldAdjuster(self::$SECOND, self::$MINUTE, 0, 59);
216: }
217: return $adjuster;
218: }
219: }
220: