PageRenderTime 50ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/framework/model/fieldtypes/Date.php

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