Passed
Push — master ( 62403d...0c3e2f )
by Joas
14:50 queued 14s
created

lib/private/DateTimeFormatter.php (1 issue)

1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author dartcafe <[email protected]>
6
 * @author Joas Schilling <[email protected]>
7
 * @author Morris Jobke <[email protected]>
8
 *
9
 * @license AGPL-3.0
10
 *
11
 * This code is free software: you can redistribute it and/or modify
12
 * it under the terms of the GNU Affero General Public License, version 3,
13
 * as published by the Free Software Foundation.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
 * GNU Affero General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU Affero General Public License, version 3,
21
 * along with this program. If not, see <http://www.gnu.org/licenses/>
22
 *
23
 */
24
25
namespace OC;
26
27
class DateTimeFormatter implements \OCP\IDateTimeFormatter {
28
	/** @var \DateTimeZone */
29
	protected $defaultTimeZone;
30
31
	/** @var \OCP\IL10N */
32
	protected $defaultL10N;
33
34
	/**
35
	 * Constructor
36
	 *
37
	 * @param \DateTimeZone $defaultTimeZone Set the timezone for the format
38
	 * @param \OCP\IL10N $defaultL10N Set the language for the format
39
	 */
40
	public function __construct(\DateTimeZone $defaultTimeZone, \OCP\IL10N $defaultL10N) {
41
		$this->defaultTimeZone = $defaultTimeZone;
42
		$this->defaultL10N = $defaultL10N;
43
	}
44
45
	/**
46
	 * Get TimeZone to use
47
	 *
48
	 * @param \DateTimeZone $timeZone	The timezone to use
49
	 * @return \DateTimeZone		The timezone to use, falling back to the current user's timezone
50
	 */
51
	protected function getTimeZone($timeZone = null) {
52
		if ($timeZone === null) {
53
			$timeZone = $this->defaultTimeZone;
54
		}
55
56
		return $timeZone;
57
	}
58
59
	/**
60
	 * Get \OCP\IL10N to use
61
	 *
62
	 * @param \OCP\IL10N $l	The locale to use
63
	 * @return \OCP\IL10N		The locale to use, falling back to the current user's locale
64
	 */
65
	protected function getLocale($l = null) {
66
		if ($l === null) {
67
			$l = $this->defaultL10N;
68
		}
69
70
		return $l;
71
	}
72
73
	/**
74
	 * Generates a DateTime object with the given timestamp and TimeZone
75
	 *
76
	 * @param mixed $timestamp
77
	 * @param \DateTimeZone $timeZone	The timezone to use
78
	 * @return \DateTime
79
	 */
80
	protected function getDateTime($timestamp, \DateTimeZone $timeZone = null) {
81
		if ($timestamp === null) {
82
			return new \DateTime('now', $timeZone);
83
		} else if (!$timestamp instanceof \DateTime) {
84
			$dateTime = new \DateTime('now', $timeZone);
85
			$dateTime->setTimestamp($timestamp);
86
			return $dateTime;
87
		}
88
		if ($timeZone) {
89
			$timestamp->setTimezone($timeZone);
90
		}
91
		return $timestamp;
92
	}
93
94
	/**
95
	 * Formats the date of the given timestamp
96
	 *
97
	 * @param int|\DateTime	$timestamp	Either a Unix timestamp or DateTime object
98
	 * @param string	$format			Either 'full', 'long', 'medium' or 'short'
99
	 * 				full:	e.g. 'EEEE, MMMM d, y'	=> 'Wednesday, August 20, 2014'
100
	 * 				long:	e.g. 'MMMM d, y'		=> 'August 20, 2014'
101
	 * 				medium:	e.g. 'MMM d, y'			=> 'Aug 20, 2014'
102
	 * 				short:	e.g. 'M/d/yy'			=> '8/20/14'
103
	 * 				The exact format is dependent on the language
104
	 * @param \DateTimeZone	$timeZone	The timezone to use
105
	 * @param \OCP\IL10N	$l			The locale to use
106
	 * @return string Formatted date string
107
	 */
108
	public function formatDate($timestamp, $format = 'long', \DateTimeZone $timeZone = null, \OCP\IL10N $l = null) {
109
		return $this->format($timestamp, 'date', $format, $timeZone, $l);
110
	}
111
112
	/**
113
	 * Formats the date of the given timestamp
114
	 *
115
	 * @param int|\DateTime	$timestamp	Either a Unix timestamp or DateTime object
116
	 * @param string	$format			Either 'full', 'long', 'medium' or 'short'
117
	 * 				full:	e.g. 'EEEE, MMMM d, y'	=> 'Wednesday, August 20, 2014'
118
	 * 				long:	e.g. 'MMMM d, y'		=> 'August 20, 2014'
119
	 * 				medium:	e.g. 'MMM d, y'			=> 'Aug 20, 2014'
120
	 * 				short:	e.g. 'M/d/yy'			=> '8/20/14'
121
	 * 				The exact format is dependent on the language
122
	 * 					Uses 'Today', 'Yesterday' and 'Tomorrow' when applicable
123
	 * @param \DateTimeZone	$timeZone	The timezone to use
124
	 * @param \OCP\IL10N	$l			The locale to use
125
	 * @return string Formatted relative date string
126
	 */
127
	public function formatDateRelativeDay($timestamp, $format = 'long', \DateTimeZone $timeZone = null, \OCP\IL10N $l = null) {
128
		if (substr($format, -1) !== '*' && substr($format, -1) !== '*') {
129
			$format .= '^';
130
		}
131
132
		return $this->format($timestamp, 'date', $format, $timeZone, $l);
133
	}
134
135
	/**
136
	 * Gives the relative date of the timestamp
137
	 * Only works for past dates
138
	 *
139
	 * @param int|\DateTime	$timestamp	Either a Unix timestamp or DateTime object
140
	 * @param int|\DateTime	$baseTimestamp	Timestamp to compare $timestamp against, defaults to current time
141
	 * @return string	Dates returned are:
142
	 * 				<  1 month	=> Today, Yesterday, n days ago
143
	 * 				< 13 month	=> last month, n months ago
144
	 * 				>= 13 month	=> last year, n years ago
145
	 * @param \OCP\IL10N	$l			The locale to use
146
	 * @return string Formatted date span
147
	 */
148
	public function formatDateSpan($timestamp, $baseTimestamp = null, \OCP\IL10N $l = null) {
149
		$l = $this->getLocale($l);
150
		$timestamp = $this->getDateTime($timestamp);
151
		$timestamp->setTime(0, 0, 0);
152
153
		if ($baseTimestamp === null) {
154
			$baseTimestamp = time();
155
		}
156
		$baseTimestamp = $this->getDateTime($baseTimestamp);
157
		$baseTimestamp->setTime(0, 0, 0);
158
		$dateInterval = $timestamp->diff($baseTimestamp);
159
160
		if ($dateInterval->y == 0 && $dateInterval->m == 0 && $dateInterval->d == 0) {
161
			return $l->t('today');
162
		} else if ($dateInterval->y == 0 && $dateInterval->m == 0 && $dateInterval->d == 1) {
163
			if ($timestamp > $baseTimestamp) {
164
				return $l->t('tomorrow');
165
			} else {
166
				return $l->t('yesterday');
167
			}
168
		} else if ($dateInterval->y == 0 && $dateInterval->m == 0) {
169
			if ($timestamp > $baseTimestamp) {
170
				return $l->n('in %n day', 'in %n days', $dateInterval->d);
171
			} else {
172
				return $l->n('%n day ago', '%n days ago', $dateInterval->d);
173
			}
174
		} else if ($dateInterval->y == 0 && $dateInterval->m == 1) {
175
			if ($timestamp > $baseTimestamp) {
176
				return $l->t('next month');
177
			} else {
178
				return $l->t('last month');
179
			}
180
		} else if ($dateInterval->y == 0) {
181
			if ($timestamp > $baseTimestamp) {
182
				return $l->n('in %n month', 'in %n months', $dateInterval->m);
183
			} else {
184
				return $l->n('%n month ago', '%n months ago', $dateInterval->m);
185
			}
186
		} else if ($dateInterval->y == 1) {
187
			if ($timestamp > $baseTimestamp) {
188
				return $l->t('next year');
189
			} else {
190
				return $l->t('last year');
191
			}
192
		}
193
		if ($timestamp > $baseTimestamp) {
194
			return $l->n('in %n year', 'in %n years', $dateInterval->y);
195
		} else {
196
			return $l->n('%n year ago', '%n years ago', $dateInterval->y);
197
		}
198
	}
199
200
	/**
201
	 * Formats the time of the given timestamp
202
	 *
203
	 * @param int|\DateTime	$timestamp	Either a Unix timestamp or DateTime object
204
	 * @param string	$format			Either 'full', 'long', 'medium' or 'short'
205
	 * 				full:	e.g. 'h:mm:ss a zzzz'	=> '11:42:13 AM GMT+0:00'
206
	 * 				long:	e.g. 'h:mm:ss a z'		=> '11:42:13 AM GMT'
207
	 * 				medium:	e.g. 'h:mm:ss a'		=> '11:42:13 AM'
208
	 * 				short:	e.g. 'h:mm a'			=> '11:42 AM'
209
	 * 				The exact format is dependent on the language
210
	 * @param \DateTimeZone	$timeZone	The timezone to use
211
	 * @param \OCP\IL10N	$l			The locale to use
212
	 * @return string Formatted time string
213
	 */
214
	public function formatTime($timestamp, $format = 'medium', \DateTimeZone $timeZone = null, \OCP\IL10N $l = null) {
215
		return $this->format($timestamp, 'time', $format, $timeZone, $l);
216
	}
217
218
	/**
219
	 * Gives the relative past time of the timestamp
220
	 *
221
	 * @param int|\DateTime	$timestamp	Either a Unix timestamp or DateTime object
222
	 * @param int|\DateTime	$baseTimestamp	Timestamp to compare $timestamp against, defaults to current time
223
	 * @return string	Dates returned are:
224
	 * 				< 60 sec	=> seconds ago
225
	 * 				<  1 hour	=> n minutes ago
226
	 * 				<  1 day	=> n hours ago
227
	 * 				<  1 month	=> Yesterday, n days ago
228
	 * 				< 13 month	=> last month, n months ago
229
	 * 				>= 13 month	=> last year, n years ago
230
	 * @param \OCP\IL10N	$l			The locale to use
231
	 * @return string Formatted time span
232
	 */
233
	public function formatTimeSpan($timestamp, $baseTimestamp = null, \OCP\IL10N $l = null) {
234
		$l = $this->getLocale($l);
235
		$timestamp = $this->getDateTime($timestamp);
236
		if ($baseTimestamp === null) {
237
			$baseTimestamp = time();
238
		}
239
		$baseTimestamp = $this->getDateTime($baseTimestamp);
240
241
		$diff = $timestamp->diff($baseTimestamp);
242
		if ($diff->y > 0 || $diff->m > 0 || $diff->d > 0) {
243
			return $this->formatDateSpan($timestamp, $baseTimestamp, $l);
244
		}
245
246
		if ($diff->h > 0) {
247
			if ($timestamp > $baseTimestamp) {
248
				return $l->n('in %n hour', 'in %n hours', $diff->h);
249
			} else {
250
				return $l->n('%n hour ago', '%n hours ago', $diff->h);
251
			}
252
		} else if ($diff->i > 0) {
253
			if ($timestamp > $baseTimestamp) {
254
				return $l->n('in %n minute', 'in %n minutes', $diff->i);
255
			} else {
256
				return $l->n('%n minute ago', '%n minutes ago', $diff->i);
257
			}
258
		}
259
		if ($timestamp > $baseTimestamp) {
260
			return $l->t('in a few seconds');
261
		} else {
262
			return $l->t('seconds ago');
263
		}
264
	}
265
266
	/**
267
	 * Formats the date and time of the given timestamp
268
	 *
269
	 * @param int|\DateTime $timestamp	Either a Unix timestamp or DateTime object
270
	 * @param string		$formatDate		See formatDate() for description
271
	 * @param string		$formatTime		See formatTime() for description
272
	 * @param \DateTimeZone	$timeZone	The timezone to use
273
	 * @param \OCP\IL10N	$l			The locale to use
274
	 * @return string Formatted date and time string
275
	 */
276
	public function formatDateTime($timestamp, $formatDate = 'long', $formatTime = 'medium', \DateTimeZone $timeZone = null, \OCP\IL10N $l = null) {
277
		return $this->format($timestamp, 'datetime', $formatDate . '|' . $formatTime, $timeZone, $l);
278
	}
279
280
	/**
281
	 * Formats the date and time of the given timestamp
282
	 *
283
	 * @param int|\DateTime $timestamp	Either a Unix timestamp or DateTime object
284
	 * @param string	$formatDate		See formatDate() for description
285
	 * 					Uses 'Today', 'Yesterday' and 'Tomorrow' when applicable
286
	 * @param string	$formatTime		See formatTime() for description
287
	 * @param \DateTimeZone	$timeZone	The timezone to use
288
	 * @param \OCP\IL10N	$l			The locale to use
289
	 * @return string Formatted relative date and time string
290
	 */
291
	public function formatDateTimeRelativeDay($timestamp, $formatDate = 'long', $formatTime = 'medium', \DateTimeZone $timeZone = null, \OCP\IL10N $l = null) {
292
		if (substr($formatDate, -1) !== '^' && substr($formatDate, -1) !== '*') {
293
			$formatDate .= '^';
294
		}
295
296
		return $this->format($timestamp, 'datetime', $formatDate . '|' . $formatTime, $timeZone, $l);
297
	}
298
299
	/**
300
	 * Formats the date and time of the given timestamp
301
	 *
302
	 * @param int|\DateTime $timestamp	Either a Unix timestamp or DateTime object
303
	 * @param string		$type		One of 'date', 'datetime' or 'time'
304
	 * @param string		$format		Format string
305
	 * @param \DateTimeZone	$timeZone	The timezone to use
306
	 * @param \OCP\IL10N	$l			The locale to use
307
	 * @return string Formatted date and time string
308
	 */
309
	protected function format($timestamp, $type, $format, \DateTimeZone $timeZone = null, \OCP\IL10N $l = null) {
310
		$l = $this->getLocale($l);
311
		$timeZone = $this->getTimeZone($timeZone);
312
		$timestamp = $this->getDateTime($timestamp, $timeZone);
313
314
		return $l->l($type, $timestamp, [
0 ignored issues
show
Bug Best Practice introduced by
The expression return $l->l($type, $tim...ay('width' => $format)) could also return false which is incompatible with the documented return type string. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
315
			'width' => $format,
316
		]);
317
	}
318
}
319