diff --git a/forms/DatetimeField.php b/forms/DatetimeField.php index f44108cd7..6d4342b0c 100644 --- a/forms/DatetimeField.php +++ b/forms/DatetimeField.php @@ -148,7 +148,7 @@ class DatetimeField extends FormField { unset($userValueObj); } else { // Validation happens later, so set the raw string in case Zend_Date doesn't accept it - $this->value = sprintf($this->getConfig('datetimeorder'), $val['date'], $val['time']); + $this->value = trim(sprintf($this->getConfig('datetimeorder'), $val['date'], $val['time'])); } if($userTz) date_default_timezone_set($dataTz); diff --git a/model/fieldtypes/Date.php b/model/fieldtypes/Date.php index 736179911..bd7048f87 100644 --- a/model/fieldtypes/Date.php +++ b/model/fieldtypes/Date.php @@ -21,17 +21,26 @@ class Date extends DBField { function setValue($value) { + if($value === false || $value === null || (is_string($value) && !strlen($value))) { + // don't try to evaluate empty values with strtotime() below, as it returns "1970-01-01" when it should be saved as NULL in database + $this->value = null; + return; + } + // @todo This needs tidy up (what if you only specify a month and a year, for example?) if(is_array($value)) { if(!empty($value['Day']) && !empty($value['Month']) && !empty($value['Year'])) { $this->value = $value['Year'] . '-' . $value['Month'] . '-' . $value['Day']; return; + } else { + // return nothing (so checks below don't fail on an empty array) + return null; } } // Default to NZ date format - strtotime expects a US date if(ereg('^([0-9]+)/([0-9]+)/([0-9]+)$', $value, $parts)) { - $value = "$parts[2]/$parts[1]/$parts[3]"; + $value = "$parts[2]/$parts[1]/$parts[3]"; } if(is_numeric($value)) { @@ -84,13 +93,18 @@ class Date extends DBField { } /** - * Returns the date of the month + * Returns the day of the month. + * @param boolean $includeOrdinals Include ordinal suffix to day, e.g. "th" or "rd" + * @return string */ - function DayOfMonth() { - if($this->value) return date('j', strtotime($this->value)); + function DayOfMonth($includeOrdinal = false) { + if($this->value) { + $format = 'j'; + if ($includeOrdinal) $format .= 'S'; + return date($format, strtotime($this->value)); + } } - /** * Returns the date in the format 24 December 2006 */ @@ -121,7 +135,7 @@ class Date extends DBField { * strftime obeys the current LC_TIME/LC_ALL when printing lexical values * like day- and month-names */ - function FormatI18N($formattingString) { + function FormatI18N($formattingString) { if($this->value) { $fecfrm = strftime($formattingString, strtotime($this->value)); return utf8_encode($fecfrm); @@ -130,10 +144,13 @@ class Date extends DBField { /* * Return a string in the form "12 - 16 Sept" or "12 Aug - 16 Sept" + * @param Date $otherDateObj Another date object specifying the end of the range + * @param boolean $includeOrdinals Include ordinal suffix to day, e.g. "th" or "rd" + * @return string */ - function RangeString($otherDateObj) { - $d1 = $this->DayOfMonth(); - $d2 = $otherDateObj->DayOfMonth(); + function RangeString($otherDateObj, $includeOrdinals = false) { + $d1 = $this->DayOfMonth($includeOrdinals); + $d2 = $otherDateObj->DayOfMonth($includeOrdinals); $m1 = $this->ShortMonth(); $m2 = $otherDateObj->ShortMonth(); $y1 = $this->Year(); @@ -357,4 +374,4 @@ class Date extends DBField { public function scaffoldFormField($title = null, $params = null) { return new DateField($this->name, $title); } -} \ No newline at end of file +} diff --git a/model/fieldtypes/Datetime.php b/model/fieldtypes/Datetime.php index 77a56688a..83cb184e2 100644 --- a/model/fieldtypes/Datetime.php +++ b/model/fieldtypes/Datetime.php @@ -26,6 +26,12 @@ class SS_Datetime extends Date { function setValue($value) { + if($value === false || $value === null || (is_string($value) && !strlen($value))) { + // don't try to evaluate empty values with strtotime() below, as it returns "1970-01-01" when it should be saved as NULL in database + $this->value = null; + return; + } + // Default to NZ date format - strtotime expects a US date if(ereg('^([0-9]+)/([0-9]+)/([0-9]+)$', $value, $parts)) { $value = "$parts[2]/$parts[1]/$parts[3]"; @@ -42,19 +48,23 @@ class SS_Datetime extends Date { * Returns the date in the raw SQL-format, e.g. “2006-01-18 16:32:04” */ function Nice() { - return date('d/m/Y g:ia', strtotime($this->value)); + if($this->value) return date('d/m/Y g:ia', strtotime($this->value)); } + function Nice24() { - return date('d/m/Y H:i', strtotime($this->value)); + if($this->value) return date('d/m/Y H:i', strtotime($this->value)); } + function Date() { - return date('d/m/Y', strtotime($this->value)); + if($this->value) return date('d/m/Y', strtotime($this->value)); } + function Time() { - return date('g:ia', strtotime($this->value)); + if($this->value) return date('g:ia', strtotime($this->value)); } + function Time24() { - return date('H:i', strtotime($this->value)); + if($this->value) return date('H:i', strtotime($this->value)); } function requireField() { @@ -64,7 +74,7 @@ class SS_Datetime extends Date { } function URLDatetime() { - return date('Y-m-d%20H:i:s', strtotime($this->value)); + if($this->value) return date('Y-m-d%20H:i:s', strtotime($this->value)); } public function scaffoldFormField($title = null, $params = null) { diff --git a/tests/model/DateTest.php b/tests/model/DateTest.php index 44b1b498d..f09da2c86 100644 --- a/tests/model/DateTest.php +++ b/tests/model/DateTest.php @@ -93,5 +93,35 @@ class DateTest extends SapphireTest { "Date->Long() works with D/M/YYYY" ); } - + + function testSetNullAndZeroValues() { + $date = DBField::create('Date', ''); + $this->assertNull($date->getValue(), 'Empty string evaluates to NULL'); + + $date = DBField::create('Date', null); + $this->assertNull($date->getValue(), 'NULL is set as NULL'); + + $date = DBField::create('Date', false); + $this->assertNull($date->getValue(), 'Boolean FALSE evaluates to NULL'); + + $date = DBField::create('Date', array()); + $this->assertNull($date->getValue(), 'Empty array evaluates to NULL'); + + $date = DBField::create('Date', '0'); + $this->assertEquals('1970-01-01', $date->getValue(), 'Zero is UNIX epoch date'); + + $date = DBField::create('Date', 0); + $this->assertEquals('1970-01-01', $date->getValue(), 'Zero is UNIX epoch date'); + } + + function testDayOfMonth() { + $date = DBField::create('Date', '2000-10-10'); + $this->assertEquals('10', $date->DayOfMonth()); + $this->assertEquals('10th', $date->DayOfMonth(true)); + + $range = $date->RangeString(DBField::create('Date', '2000-10-20')); + $this->assertEquals('10 - 20 Oct 2000', $range); + $range = $date->RangeString(DBField::create('Date', '2000-10-20'), true); + $this->assertEquals('10th - 20th Oct 2000', $range); + } } diff --git a/tests/model/DatetimeTest.php b/tests/model/DatetimeTest.php index b18c6fb01..f3636ef6a 100644 --- a/tests/model/DatetimeTest.php +++ b/tests/model/DatetimeTest.php @@ -33,4 +33,22 @@ class SS_DatetimeTest extends SapphireTest { $nowDatetime = SS_Datetime::now(); $this->assertEquals($systemDatetime->Date(), $nowDatetime->Date()); } -} \ No newline at end of file + + function testSetNullAndZeroValues() { + $date = DBField::create('SS_Datetime', ''); + $this->assertNull($date->getValue(), 'Empty string evaluates to NULL'); + + $date = DBField::create('SS_Datetime', null); + $this->assertNull($date->getValue(), 'NULL is set as NULL'); + + $date = DBField::create('SS_Datetime', false); + $this->assertNull($date->getValue(), 'Boolean FALSE evaluates to NULL'); + + $date = DBField::create('SS_Datetime', '0'); + $this->assertEquals('1970-01-01 12:00:00', $date->getValue(), 'Zero is UNIX epoch time'); + + $date = DBField::create('SS_Datetime', 0); + $this->assertEquals('1970-01-01 12:00:00', $date->getValue(), 'Zero is UNIX epoch time'); + } + +}