Version: current

      1 <?php
      2 /**
      3  * Represents a date field.
      4  * The field currently supports New Zealand date format (DD/MM/YYYY),
      5  * or an ISO 8601 formatted date (YYYY-MM-DD).
      6  * Alternatively you can set a timestamp that is evaluated through
      7  * PHP's built-in date() function according to your system locale.
      8  *
      9  * @todo Add localization support, see http://open.silverstripe.com/ticket/2931
     10  *
     11  * @package sapphire
     12  * @subpackage model
     13  */
     14 class Date extends DBField {
     15
     16     function setValue($value) {
     17         // @todo This needs tidy up (what if you only specify a month and a year, for example?)
     18         if(is_array($value)) {
     19             if(!empty($value['Day']) && !empty($value['Month']) && !empty($value['Year'])) {
     20                 $this->value = $value['Year'] . '-' . $value['Month'] . '-' . $value['Day'];
     21                 return;
     22             }
     23         }
     24
     25         // Default to NZ date format - strtotime expects a US date
     26         if(ereg('^([0-9]+)/([0-9]+)/([0-9]+)$', $value, $parts)) {
     27             $value = "$parts[2]/$parts[1]/$parts[3]";
     28         }
     29
     30         if(is_numeric($value)) {
     31             $this->value = date('Y-m-d', $value);
     32         } elseif(is_string($value)) {
     33             $this->value = date('Y-m-d', strtotime($value));
     34         }
     35     }
     36
     37     /**
     38      * Returns the date in the format dd/mm/yy
     39      * TODO i18n formatting for NIce
     40      */
     41     function Nice() {
     42         if($this->value) return date('d/m/Y', strtotime($this->value));
     43     }
     44
     45     function NiceUS() {
     46         if($this->value) return date('m/d/Y', strtotime($this->value));
     47     }
     48
     49     /**
     50      * Returns the year from the given date
     51      */
     52     function Year() {
     53         if($this->value) return date('Y', strtotime($this->value));
     54     }
     55
     56     /**
     57      * Returns the Full day, of the given date.
     58      */
     59     function Day(){
     60         if($this->value) return strftime('%A', strtotime($this->value));
     61     }
     62
     63     /**
     64      * Returns the month
     65      */
     66     function ShortMonth() {
     67         if($this->value) return strftime('%b', strtotime($this->value));
     68     }
     69
     70     /**
     71      * Returns the date of the month
     72      */
     73     function DayOfMonth() {
     74         if($this->value) return date('j', strtotime($this->value));
     75     }
     76
     77         function Month(){
     78             if($this->value) return date('m', strtotime($this->value));
     79         }
     80
     81     /**
     82      * Returns the date in the format 24 December 2006
     83      */
     84     function Long() {
     85         if($this->value) return date('j F Y', strtotime($this->value));
     86     }
     87
     88     /**
     89      * Returns the date in the format 24 Dec 2006
     90      */
     91     function Full() {
     92         if($this->value) return date('j M Y', strtotime($this->value));
     93     }
     94
     95     /**
     96      * Return the date using a particular formatting string.
     97      *
     98      * @param string $format Format code string. e.g. "d M Y"
     99      * @return string The date in the requested format
    100      */
    101     function Format($format) {
    102         if($this->value) return date($format, strtotime($this->value));
    103     }
    104
    105     /**
    106      * Return the date formatted using the given strftime formatting string.
    107      *
    108      * strftime obeys the current LC_TIME/LC_ALL when printing lexical values
    109      * like day- and month-names
    110      */
    111     function FormatI18N($formattingString) {
    112         if($this->value) return i18n::strftime($formattingString, strtotime($this->value));
    113     }
    114
    115     /*
    116      * Return a string in the form "12 - 16 Sept" or "12 Aug - 16 Sept"
    117      */
    118     function RangeString($otherDateObj) {
    119         $d1 = $this->DayOfMonth();
    120         $d2 = $otherDateObj->DayOfMonth();
    121         $m1 = $this->ShortMonth();
    122         $m2 = $otherDateObj->ShortMonth();
    123         $y1 = $this->Year();
    124         $y2 = $otherDateObj->Year();
    125
    126         if($y1 != $y2) return "$d1 $m1 $y1 - $d2 $m2 $y2";
    127         else if($m1 != $m2) return "$d1 $m1 - $d2 $m2 $y1";
    128         else return "$d1 - $d2 $m1 $y1";
    129     }
    130
    131     function Rfc822() {
    132         if($this->value) return date('r', strtotime($this->value));
    133     }
    134
    135     function Rfc2822() {
    136         if($this->value) return date('Y-m-d H:i:s', strtotime($this->value));
    137     }
    138
    139     function Rfc3339() {
    140         $timestamp = ($this->value) ? strtotime($this->value) : false;
    141         if(!$timestamp) return false;
    142
    143         $date = date('Y-m-d\TH:i:s', $timestamp);
    144
    145         $matches = array();
    146         if(preg_match('/^([\-+])(\d{2})(\d{2})$/', date('O', $timestamp), $matches)) {
    147             $date .= $matches[1].$matches[2].':'.$matches[3];
    148         } else {
    149             $date .= 'Z';
    150         }
    151
    152         return $date;
    153     }
    154
    155     /**
    156      * Returns the number of seconds/minutes/hours/days or months since the timestamp
    157      */
    158     function Ago() {
    159         if($this->value) {
    160             if(strtotime($this->value) == time() || time() > strtotime($this->value)) {
    161                 return sprintf(
    162                     _t(
    163                         'Date.TIMEDIFFAGO',
    164                         "%s ago",
    165                         PR_MEDIUM,
    166                         'Natural language time difference, e.g. 2 hours ago'
    167                     ),
    168                     $this->TimeDiff()
    169                 );
    170             } else {
    171                 return sprintf(
    172                     _t(
    173                         'Date.TIMEDIFFAWAY',
    174                         "%s away",
    175                         PR_MEDIUM,
    176                         'Natural language time difference, e.g. 2 hours away'
    177                     ),
    178                     $this->TimeDiff()
    179                 );
    180             }
    181         }
    182     }
    183
    184     function TimeDiff() {
    185
    186         if($this->value) {
    187             $ago = abs(time() - strtotime($this->value));
    188
    189             if($ago < 60) {
    190                 $span = $ago;
    191                 return ($span != 1) ? "{$span} "._t("Date.SECS", " secs") : "{$span} "._t("Date.SEC", " sec");
    192             }
    193             if($ago < 3600) {
    194                 $span = round($ago/60);
    195                 return ($span != 1) ? "{$span} "._t("Date.MINS", " mins") : "{$span} "._t("Date.MIN", " min");
    196             }
    197             if($ago < 86400) {
    198                 $span = round($ago/3600);
    199                 return ($span != 1) ? "{$span} "._t("Date.HOURS", " hours") : "{$span} "._t("Date.HOUR", " hour");
    200             }
    201             if($ago < 86400*30) {
    202                 $span = round($ago/86400);
    203                 return ($span != 1) ? "{$span} "._t("Date.DAYS", " days") : "{$span} "._t("Date.DAY", " day");
    204             }
    205             if($ago < 86400*365) {
    206                 $span = round($ago/86400/30);
    207                 return ($span != 1) ? "{$span} "._t("Date.MONTHS", " months") : "{$span} "._t("Date.MONTH", " month");
    208             }
    209             if($ago > 86400*365) {
    210                 $span = round($ago/86400/365);
    211                 return ($span != 1) ? "{$span} "._t("Date.YEARS", " years") : "{$span} "._t("Date.YEAR", " year");
    212             }
    213         }
    214     }
    215
    216     /**
    217      * Gets the time difference, but always returns it in a certain format
    218      * @param string $format The format, could be one of these:
    219      * 'seconds', 'minutes', 'hours', 'days', 'months', 'years'.
    220      *
    221      * @return string
    222      */
    223     function TimeDiffIn($format) {
    224         if($this->value) {
    225             $ago = abs(time() - strtotime($this->value));
    226
    227             switch($format) {
    228                 case "seconds":
    229                     $span = $ago;
    230                     return ($span != 1) ? "{$span} seconds" : "{$span} second";
    231                 break;
    232                 case "minutes":
    233                     $span = round($ago/60);
    234                     return ($span != 1) ? "{$span} minutes" : "{$span} minute";
    235                 break;
    236                 case "hours":
    237                     $span = round($ago/3600);
    238                     return ($span != 1) ? "{$span} hours" : "{$span} hour";
    239                 break;
    240                 case "days":
    241                     $span = round($ago/86400);
    242                     return ($span != 1) ? "{$span} days" : "{$span} day";
    243                 break;
    244                 case "months":
    245                     $span = round($ago/86400/30);
    246                     return ($span != 1) ? "{$span} months" : "{$span} month";
    247                 break;
    248                 case "years":
    249                     $span = round($ago/86400/365);
    250                     return ($span != 1) ? "{$span} years" : "{$span} year";
    251                 break;
    252             }
    253         }
    254     }
    255
    256     function requireField() {
    257         $parts=Array('datatype'=>'date', 'arrayValue'=>$this->arrayValue);
    258         $values=Array('type'=>'date', 'parts'=>$parts);
    259         DB::requireField($this->tableName, $this->name, $values);
    260     }
    261
    262     /**
    263      * Returns true if date is in the past.
    264      * @return boolean
    265      */
    266     function InPast() {
    267         return strtotime($this->value) < time();
    268     }
    269
    270     /**
    271      * Returns true if date is in the future.
    272      * @return boolean
    273      */
    274     function InFuture() {
    275         return strtotime($this->value) > time();
    276     }
    277
    278     /**
    279      * Returns true if date is today.
    280      * @return boolean
    281      */
    282     function IsToday() {
    283         return (date('Y-m-d', strtotime($this->value)) == date('Y-m-d', time()));
    284     }
    285
    286     /**
    287      * Returns a date suitable for insertion into a URL and use by the system.
    288      */
    289     function URLDate() {
    290         return date('Y-m-d', strtotime($this->value));
    291     }
    292
    293
    294     function days_between($fyear, $fmonth, $fday, $tyear, $tmonth, $tday){
    295       return abs((mktime ( 0, 0, 0, $fmonth, $fday, $fyear) - mktime ( 0, 0, 0, $tmonth, $tday, $tyear))/(60*60*24));
    296     }
    297
    298     function day_before($fyear, $fmonth, $fday){
    299       return date ("Y-m-d", mktime (0,0,0,$fmonth,$fday-1,$fyear));
    300     }
    301
    302     function next_day($fyear, $fmonth, $fday){
    303       return date ("Y-m-d", mktime (0,0,0,$fmonth,$fday+1,$fyear));
    304     }
    305
    306     function weekday($fyear, $fmonth, $fday){ // 0 is a Monday
    307       return (((mktime ( 0, 0, 0, $fmonth, $fday, $fyear) - mktime ( 0, 0, 0, 7, 17, 2006))/(60*60*24))+700000) % 7;
    308     }
    309
    310     function prior_monday($fyear, $fmonth, $fday){
    311       return date ("Y-m-d", mktime (0,0,0,$fmonth,$fday-weekday($fyear, $fmonth, $fday),$fyear));
    312     }
    313
    314     /**
    315      * Return the nearest date in the past, based on day and month.
    316      * Automatically attaches the correct year.
    317      *
    318      * This is useful for determining a financial year start or end date.
    319      *
    320      * @param $fmonth int The number of the month (e.g. 3 is March, 4 is April)
    321      * @param $fday int The day of the month
    322      * @param $fyear int Determine historical value
    323      * @return string Date in YYYY-MM-DD format
    324      */
    325     static function past_date($fmonth, $fday = 1, $fyear = null) {
    326         if(!$fyear) $fyear = date('Y');
    327         $fday = (int) $fday;
    328         $fmonth = (int) $fmonth;
    329         $fyear = (int) $fyear;
    330
    331         $pastDate = mktime(0, 0, 0, $fmonth, $fday, $fyear);
    332         $curDate = mktime(0, 0, 0, date('m'), date('d'), $fyear);
    333
    334         if($pastDate < $curDate) {
    335             return date('Y-m-d', mktime(0, 0, 0, $fmonth, $fday, $fyear));
    336         } else {
    337             return date('Y-m-d', mktime(0, 0, 0, $fmonth, $fday, $fyear - 1));
    338         }
    339     }
    340
    341     public function scaffoldFormField($title = null, $params = null) {
    342         return new DateField($this->name, $title);
    343     }
    344
    345 }
    346 ?>
    347

[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the Silverstripe Forums to ask development related questions. -