Overview

Namespaces

  • Peach
    • DF
    • DT
    • Http
      • Body
      • Header
    • Markup
    • Util

Classes

  • Peach\DF\Base64Codec
  • Peach\DF\CodecChain
  • Peach\DF\JsonCodec
  • Peach\DF\SerializationCodec
  • Peach\DF\Utf8Codec
  • Peach\DT\AbstractTime
  • Peach\DT\Clock
  • Peach\DT\Date
  • Peach\DT\Datetime
  • Peach\DT\DefaultClock
  • Peach\DT\FixedClock
  • Peach\DT\FormatWrapper
  • Peach\DT\HttpDateFormat
  • Peach\DT\OffsetClock
  • Peach\DT\ShiftFormat
  • Peach\DT\SimpleFormat
  • Peach\DT\TimeEquator
  • Peach\DT\Timestamp
  • Peach\DT\TimeWrapper
  • Peach\DT\UnixTimeFormat
  • Peach\DT\Util
  • Peach\DT\W3cDatetimeFormat
  • Peach\Http\Body
  • Peach\Http\Body\CodecRenderer
  • Peach\Http\Body\StringRenderer
  • Peach\Http\DefaultEndpoint
  • Peach\Http\Header\CookieItem
  • Peach\Http\Header\CookieOptions
  • Peach\Http\Header\HttpDate
  • Peach\Http\Header\NoField
  • Peach\Http\Header\QualityValues
  • Peach\Http\Header\Raw
  • Peach\Http\Header\SetCookie
  • Peach\Http\Header\Status
  • Peach\Http\Request
  • Peach\Http\Response
  • Peach\Http\Util
  • Peach\Markup\AbstractHelper
  • Peach\Markup\AbstractRenderer
  • Peach\Markup\BaseHelper
  • Peach\Markup\BreakControlWrapper
  • Peach\Markup\Builder
  • Peach\Markup\Code
  • Peach\Markup\Comment
  • Peach\Markup\ContainerElement
  • Peach\Markup\Context
  • Peach\Markup\DebugBuilder
  • Peach\Markup\DebugContext
  • Peach\Markup\DefaultBreakControl
  • Peach\Markup\DefaultBuilder
  • Peach\Markup\DefaultContext
  • Peach\Markup\Element
  • Peach\Markup\EmptyElement
  • Peach\Markup\HelperObject
  • Peach\Markup\HtmlHelper
  • Peach\Markup\Indent
  • Peach\Markup\MinimalBreakControl
  • Peach\Markup\NameBreakControl
  • Peach\Markup\NameValidator
  • Peach\Markup\NodeList
  • Peach\Markup\None
  • Peach\Markup\SgmlRenderer
  • Peach\Markup\Text
  • Peach\Markup\XmlRenderer
  • Peach\Util\AbstractMapEntry
  • Peach\Util\ArrayMap
  • Peach\Util\ArrayMapEntry
  • Peach\Util\Arrays
  • Peach\Util\DefaultComparator
  • Peach\Util\DefaultEquator
  • Peach\Util\HashMap
  • Peach\Util\HashMapEntry
  • Peach\Util\Strings
  • Peach\Util\Values

Interfaces

  • Peach\DF\Codec
  • Peach\DT\Format
  • Peach\DT\Time
  • Peach\Http\BodyRenderer
  • Peach\Http\Endpoint
  • Peach\Http\HeaderField
  • Peach\Http\MultiHeaderField
  • Peach\Http\SingleHeaderField
  • Peach\Markup\BreakControl
  • Peach\Markup\Component
  • Peach\Markup\Container
  • Peach\Markup\Helper
  • Peach\Markup\Node
  • Peach\Markup\Renderer
  • Peach\Util\Comparable
  • Peach\Util\Comparator
  • Peach\Util\Equator
  • Peach\Util\Map
  • Peach\Util\MapEntry
  • Overview
  • Namespace
  • Class
  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:  * DATE 型の時間オブジェクトです.
 34:  * このクラスは年・月・日のフィールドをサポートします.
 35:  */
 36: class Date extends AbstractTime
 37: {
 38:     /**
 39:      * 年の値です.
 40:      * @var int
 41:      * @ignore
 42:      */
 43:     protected $year;
 44:     
 45:     /**
 46:      * 月の値です.
 47:      * @var int
 48:      * @ignore
 49:      */
 50:     protected $month;
 51:     
 52:     /**
 53:      * 日の値です.
 54:      * @var int
 55:      * @ignore
 56:      */
 57:     protected $date;
 58:     
 59:     /**
 60:      * 現在の日付の Date オブジェクトを返します.
 61:      * 
 62:      * @param  Clock $clock 現在時刻を取得するための Clock オブジェクト
 63:      * @return Date         現在の日付をあらわす Date オブジェクト
 64:      */
 65:     public static function now(Clock $clock = null)
 66:     {
 67:         if ($clock === null) {
 68:             return self::now(DefaultClock::getInstance());
 69:         }
 70:         
 71:         return $clock->getTimestamp()->toDate();
 72:     }
 73:     
 74:     /**
 75:      * 指定された文字列を解析して Date オブジェクトに変換します.
 76:      * $format が指定されていない場合は {@link W3cDatetimeFormat::getInstance}
 77:      * を使って解析を行います.
 78:      * ("YYYY-MM-DD" 形式の文字列を受理します.)
 79:      * 
 80:      * @param  string $text   変換対象の文字列
 81:      * @param  Format $format 変換に使用するフォーマット
 82:      * @return Date           変換結果の Date オブジェクト
 83:      */
 84:     public static function parse($text, Format $format = null)
 85:     {
 86:         if (!isset($format)) {
 87:             $format = W3cDatetimeFormat::getInstance();
 88:         }
 89:         return $format->parseDate($text);
 90:     }
 91:     
 92:     /**
 93:      * 与えられた日付を表現する Peach_DT_Date オブジェクトを構築します.
 94:      *
 95:      * @param int $year  年
 96:      * @param int $month 月
 97:      * @param int $date  日
 98:      */
 99:     public function __construct($year, $month, $date)
100:     {
101:         $fields = new ArrayMap();
102:         $fields->put(self::$YEAR,  intval($year));
103:         $fields->put(self::$MONTH, intval($month));
104:         $fields->put(self::$DATE,  intval($date));
105:         $this->init($fields);
106:     }
107:     
108:     /**
109:      * このオブジェクトの型 {@link Time::TYPE_DATE} を返します.
110:      * @return int Time::TYPE_DATE
111:      */
112:     public function getType()
113:     {
114:         return self::TYPE_DATE;
115:     }
116:     
117:     /**
118:      * (non-PHPdoc)
119:      * @see AbstractTime::init
120:      * @ignore
121:      */
122:     protected function init(Map $fields)
123:     {
124:         parent::init($fields);
125:         $this->year  = $fields->get(self::$YEAR);
126:         $this->month = $fields->get(self::$MONTH);
127:         $this->date  = $fields->get(self::$DATE);
128:     }
129:     
130:     /**
131:      * 年月日の不整合を調整します.
132:      * @ignore
133:      */
134:     protected function adjust(Map $fields)
135:     {
136:         // 年と月の不整合を調整します.
137:         $this->adjustMonth($fields);
138:         
139:         $year  = $fields->get(self::$YEAR);
140:         $month = $fields->get(self::$MONTH);
141:         $date  = $fields->get(self::$DATE);
142:         
143:         // 日が1より小さい場合は、月の繰り下げ調整をします.
144:         if ($date < 1) {
145:             while ($date < 1) {
146:                 $month --;
147:                 if ($month === 0) {
148:                     $month = 12;
149:                     $year --;
150:                 }
151:                 $fields->put(self::$YEAR,  $year);
152:                 $fields->put(self::$MONTH, $month);
153:                 $date += self::getDateCountOf($year, $month);
154:             }
155:             $fields->put(self::$DATE, $date);
156:             $this->adjust($fields);
157:             return;
158:         }
159:         
160:         // 日がこの月の日数より大きい場合は、月の繰上げ調整をします.
161:         $dateCount = self::getDateCountOf($year, $month);
162:         if ($dateCount < $date) {
163:             while ($dateCount < $date) {
164:                 $date -= $dateCount;
165:                 $month ++;
166:                 if ($month === 13) {
167:                     $month = 1;
168:                     $year ++;
169:                 }
170:                 $fields->put(self::$YEAR,  $year);
171:                 $fields->put(self::$MONTH, $month);
172:                 $dateCount = self::getDateCountOf($year, $month);
173:             }
174:             $fields->put(self::$DATE, $date);
175:             $this->adjust($fields);
176:             return;
177:         }
178:     }
179:     
180:     /**
181:      * 年と月の不整合を調整します.
182:      * @param Map $fields 調整対象のフィールド一覧
183:      */
184:     private function adjustMonth(Map $fields)
185:     {
186:         // 年の不整合を調整します.
187:         $this->adjustYear($fields);
188:         $adjuster = $this->getMonthAdjuster();
189:         $month    = $fields->get(self::$MONTH);
190:         if ($month < 1) {
191:             $adjuster->moveDown($fields);
192:         } else if (12 < $month) {
193:             $adjuster->moveUp($fields);
194:         } else {
195:             return;
196:         }
197:         $this->adjustMonth($fields);
198:     }
199:     
200:     /**
201:      * 月の調整をするための FieldAdjuster を返します.
202:      * 
203:      * @return FieldAdjuster
204:      * @codeCoverageIgnore
205:      */
206:     private function getMonthAdjuster()
207:     {
208:         static $adjuster = null;
209:         if (!isset($adjuster)) {
210:             $adjuster = new FieldAdjuster(self::$MONTH, self::$YEAR, 1, 12);
211:         }
212:         return $adjuster;
213:     }
214:     
215:     /**
216:      * 年の値を4桁に調整します. (10000年問題に対応するまでの暫定的処置です.)
217:      * @param Map $fields 調整対象のフィールド一覧
218:      */
219:     private function adjustYear(Map $fields)
220:     {
221:         $year = $fields->get(self::$YEAR);
222:         $year %= 10000;
223:         if ($year < 0) {
224:             $year += 10000;
225:         }
226:         $fields->put(self::$YEAR, $year);
227:     }
228:     
229:     /**
230:      * (non-PHPdoc)
231:      * @return Date
232:      * @see Time::newInstance
233:      * @ignore
234:      */
235:     protected function newInstance(Map $fields)
236:     {
237:         $year  = $fields->get(self::$YEAR);
238:         $month = $fields->get(self::$MONTH);
239:         $date  = $fields->get(self::$DATE);
240:         return new self($year, $month, $date);
241:     }
242:     
243:     /**
244:      * この時間と指定された時間を比較します.
245:      *
246:      * この型の時間フィールドと引数の型の時間フィールドのうち,
247:      * 共通しているフィールド同士を比較します.
248:      * 
249:      * 引数が Peach_DT_Date を継承したオブジェクトではない場合,
250:      * 引数のオブジェクトに対して get("year"), get("month"), get("date") の返り値を比較対象のフィールドとします.
251:      * 
252:      * @param  Time 比較対象の時間
253:      * @return int  この時間のほうが過去の場合は負の値, 未来の場合は正の値, 等しい場合は 0
254:      * @ignore
255:      */
256:     protected function compareFields(Time $time)
257:     {
258:         $className = __CLASS__;
259:         if ($time instanceof $className) {
260:             if ($this->year  !== $time->year) {
261:                 return $this->year  - $time->year;
262:             }
263:             if ($this->month !== $time->month) {
264:                 return $this->month - $time->month;
265:             }
266:             if ($this->date  !== $time->date) {
267:                 return $this->date  - $time->date;
268:             }
269:             return 0;
270:         }
271:         else {
272:             $y = $time->get("year");
273:             $m = $time->get("month");
274:             $d = $time->get("date");
275:             if ($this->year  !== $y) {
276:                 return (isset($y) ? $this->year  - $y : 0);
277:             }
278:             if ($this->month !== $m) {
279:                 return (isset($m) ? $this->month - $m : 0);
280:             }
281:             if ($this->date  !== $d) {
282:                 return (isset($d) ? $this->date  - $d : 0);
283:             }
284:             return 0;
285:         }
286:     }
287:     
288:     /**
289:      * @return string
290:      * @ignore
291:      */
292:     protected function handleFormat(Format $format)
293:     {
294:         return $format->formatDate($this);
295:     }
296:     
297:     /**
298:      * このオブジェクトの文字列表現です.
299:      * "YYYY-MM-DD" 形式の文字列を返します.
300:      * 
301:      * @return string "YYYY-MM-DD" 形式の文字列
302:      */
303:     public function __toString()
304:     {
305:         $y = str_pad($this->year,  4, '0', STR_PAD_LEFT);
306:         $m = str_pad($this->month, 2, '0', STR_PAD_LEFT);
307:         $d = str_pad($this->date,  2, '0', STR_PAD_LEFT);
308:         return $y . '-' . $m . '-' . $d;
309:     }
310:     
311:     /**
312:      * このオブジェクトを Date 型にキャストします.
313:      * 返り値はこのオブジェクトのクローンです.
314:      *
315:      * @return Date このオブジェクトのクローン
316:      */
317:     public function toDate()
318:     {
319:         return new self($this->year, $this->month, $this->date);
320:     }
321:     
322:     /**
323:      * このオブジェクトを Datetime 型にキャストします.
324:      * この日付の 0 時 0 分を表す Datetime オブジェクトを返します.
325:      *
326:      * @return Datetime このオブジェクトの時刻表現
327:      */
328:     public function toDatetime()
329:     {
330:         return new Datetime($this->year, $this->month, $this->date, 0, 0);
331:     }
332:     
333:     /**
334:      * このオブジェクトを Timestamp 型にキャストします.
335:      * この日付の 0 時 0 分 0 秒を表す Timestamp オブジェクトを返します.
336:      *
337:      * @return Timestamp このオブジェクトの時刻表現
338:      */
339:     public function toTimestamp()
340:     {
341:         return new Timestamp($this->year, $this->month, $this->date, 0, 0, 0);
342:     }
343:     
344:     /**
345:      * この日付の曜日を返します. 返される値は 0 から 6 までの整数で, 0 が日曜, 6 が土曜をあらわします.
346:      * それぞれの整数は, このクラスで定義されている各定数に対応しています.
347:      * 
348:      * @return int 曜日 (0 以上 6 以下の整数)
349:      * 
350:      * @see    Time::SUNDAY
351:      * @see    Time::MONDAY
352:      * @see    Time::TUESDAY
353:      * @see    Time::WEDNESDAY
354:      * @see    Time::THURSDAY
355:      * @see    Time::FRIDAY
356:      * @see    Time::SATURDAY
357:      */
358:     public function getDay()
359:     {
360:         return self::getDayOf($this->year, $this->month, $this->date);
361:     }
362:     
363:     /**
364:      * この年がうるう年かどうかを判定します.
365:      *
366:      * うるう年の判別ルールは以下の通りです.
367:      * - 4 で割り切れるはうるう年である
368:      * - ただし 100 で割り切れる年はうるう年ではない
369:      * - ただし 400 で割り切れる年はうるう年である
370:      * 
371:      * @return bool うるう年である場合に TRUE, それ以外は FALSE
372:      */
373:     public function isLeapYear()
374:     {
375:         return self::checkLeapYear($this->year);
376:     }
377:     
378:     /**
379:      * 指定された年がうるう年かどうかを判定します.
380:      * 
381:      * @param  int $year 判定対象の年
382:      * @return bool      うるう年である場合に TRUE, それ以外は FALSE
383:      */
384:     private static function checkLeapYear($year)
385:     {
386:         if ($year % 4 !== 0) {
387:             return false;
388:         }
389:         if ($year % 100 !== 0) {
390:             return true;
391:         }
392:         return ($year % 400 === 0);
393:     }
394:     
395:     /**
396:      * この月の日数を返します.
397:      * @return int この月の日数. すなわち, 28 から 31 までの整数.
398:      */
399:     public function getDateCount()
400:     {
401:         return self::getDateCountOf($this->year, $this->month);
402:     }
403:     
404:     /**
405:      * 指定された月の日数を返します.
406:      * @param  int $year  年
407:      * @param  int $month 月
408:      * @return int        引数で指定された月の日数. すなわち, 28 から 31 までの整数.
409:      */
410:     private static function getDateCountOf($year, $month)
411:     {
412:         switch ($month) {
413:             case 1:  return 31;
414:             case 2:  return (self::checkLeapYear($year)) ? 29 : 28;
415:             case 3:  return 31;
416:             case 4:  return 30;
417:             case 5:  return 31;
418:             case 6:  return 30;
419:             case 7:  return 31;
420:             case 8:  return 31;
421:             case 9:  return 30;
422:             case 10: return 31;
423:             case 11: return 30;
424:             case 12: return 31;
425:         }
426:         // @codeCoverageIgnoreStart
427:         throw new \Exception();
428:         // @codeCoverageIgnoreEnd
429:     }
430: }
431: 
PEACH2 API documentation generated by ApiGen