]> git.mxchange.org Git - friendica.git/blob - src/Util/DateTimeFormat.php
- Revert HTTPSignature change
[friendica.git] / src / Util / DateTimeFormat.php
1 <?php
2 /**
3  * @copyright Copyright (C) 2010-2021, the Friendica project
4  *
5  * @license GNU AGPL version 3 or any later version
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU Affero General Public License as
9  * published by the Free Software Foundation, either version 3 of the
10  * License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Affero General Public License for more details.
16  *
17  * You should have received a copy of the GNU Affero General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19  *
20  */
21
22 namespace Friendica\Util;
23
24 use Friendica\Core\Logger;
25 use DateTime;
26 use DateTimeZone;
27 use Exception;
28
29 /**
30  * Temporal class
31  */
32 class DateTimeFormat
33 {
34         const ATOM  = 'Y-m-d\TH:i:s\Z';
35         const MYSQL = 'Y-m-d H:i:s';
36         const HTTP  = 'D, d M Y H:i:s \G\M\T';
37         const JSON  = 'Y-m-d\TH:i:s.v\Z';
38
39         /**
40          * convert() shorthand for UTC.
41          *
42          * @param string $time   A date/time string
43          * @param string $format DateTime format string or Temporal constant
44          * @return string
45          * @throws Exception
46          */
47         public static function utc($time, $format = self::MYSQL)
48         {
49                 return self::convert($time, 'UTC', 'UTC', $format);
50         }
51
52         /**
53          * convert() shorthand for local.
54          *
55          * @param string $time   A date/time string
56          * @param string $format DateTime format string or Temporal constant
57          * @return string
58          * @throws Exception
59          */
60         public static function local($time, $format = self::MYSQL)
61         {
62                 return self::convert($time, date_default_timezone_get(), 'UTC', $format);
63         }
64
65         /**
66          * convert() shorthand for timezoned now.
67          *
68          * @param        $timezone
69          * @param string $format DateTime format string or Temporal constant
70          * @return string
71          * @throws Exception
72          */
73         public static function timezoneNow($timezone, $format = self::MYSQL)
74         {
75                 return self::convert('now', $timezone, 'UTC', $format);
76         }
77
78         /**
79          * convert() shorthand for local now.
80          *
81          * @param string $format DateTime format string or Temporal constant
82          * @return string
83          * @throws Exception
84          */
85         public static function localNow($format = self::MYSQL)
86         {
87                 return self::local('now', $format);
88         }
89
90         /**
91          * convert() shorthand for UTC now.
92          *
93          * @param string $format DateTime format string or Temporal constant
94          * @return string
95          * @throws Exception
96          */
97         public static function utcNow($format = self::MYSQL)
98         {
99                 return self::utc('now', $format);
100         }
101
102         /**
103          * General purpose date parse/convert/format function.
104          *
105          * @param string $s       Some parseable date/time string
106          * @param string $tz_to   Destination timezone
107          * @param string $tz_from Source timezone
108          * @param string $format  Output format recognised from php's DateTime class
109          *                        http://www.php.net/manual/en/datetime.format.php
110          *
111          * @return string Formatted date according to given format
112          * @throws Exception
113          */
114         public static function convert($s = 'now', $tz_to = 'UTC', $tz_from = 'UTC', $format = self::MYSQL)
115         {
116                 // Defaults to UTC if nothing is set, but throws an exception if set to empty string.
117                 // Provide some sane defaults regardless.
118                 if ($tz_from === '') {
119                         $tz_from = 'UTC';
120                 }
121
122                 if ($tz_to === '') {
123                         $tz_to = 'UTC';
124                 }
125
126                 if (($s === '') || (!is_string($s))) {
127                         $s = 'now';
128                 }
129
130                 /*
131                  * Slight hackish adjustment so that 'zero' datetime actually returns what is intended
132                  * otherwise we end up with -0001-11-30 ...
133                  * add 32 days so that we at least get year 00, and then hack around the fact that
134                  * months and days always start with 1.
135                  */
136                 if (substr($s, 0, 10) <= '0001-01-01') {
137                         if ($s < '0000-00-00') {
138                                 $s = '0000-00-00';
139                         }
140                         $d = new DateTime($s . ' + 32 days', new DateTimeZone('UTC'));
141                         return str_replace('1', '0', $d->format($format));
142                 }
143
144                 try {
145                         $from_obj = new DateTimeZone($tz_from);
146                 } catch (Exception $e) {
147                         $from_obj = new DateTimeZone('UTC');
148                 }
149
150                 try {
151                         $d = new DateTime($s, $from_obj);
152                 } catch (Exception $e) {
153                         Logger::log('DateTimeFormat::convert: exception: ' . $e->getMessage());
154                         $d = new DateTime('now', $from_obj);
155                 }
156
157                 try {
158                         $to_obj = new DateTimeZone($tz_to);
159                 } catch (Exception $e) {
160                         $to_obj = new DateTimeZone('UTC');
161                 }
162
163                 $d->setTimeZone($to_obj);
164
165                 return $d->format($format);
166         }
167
168         /**
169          * Checks, if the given string is a date with the pattern YYYY-MM
170          *
171          * @param string $dateString The given date
172          *
173          * @return boolean True, if the date is a valid pattern
174          */
175         public function isYearMonth(string $dateString)
176         {
177                 // Check format (2019-01, 2019-1, 2019-10)
178                 if (!preg_match('/^([12]\d{3}-(1[0-2]|0[1-9]|\d))$/', $dateString)) {
179                         return false;
180                 }
181
182                 $date = DateTime::createFromFormat('Y-m', $dateString);
183
184                 if (!$date) {
185                         return false;
186                 }
187
188                 try {
189                         $now = new DateTime();
190                 } catch (\Throwable $t) {
191                         return false;
192                 }
193
194                 if ($date > $now) {
195                         return false;
196                 }
197
198                 return true;
199         }
200
201         /**
202          * Checks, if the given string is a date with the pattern YYYY-MM-DD
203          *
204          * @param string $dateString The given date
205          *
206          * @return boolean True, if the date is a valid pattern
207          */
208         public function isYearMonthDay(string $dateString)
209         {
210                 $date = DateTime::createFromFormat('Y-m-d', $dateString);
211                 if (!$date) {
212                         return false;
213                 }
214
215                 if (DateTime::getLastErrors()['error_count'] || DateTime::getLastErrors()['warning_count']) {
216                         return false;
217                 }
218
219                 return true;
220         }
221 }