DateParser   B
last analyzed

Complexity

Total Complexity 37

Size/Duplication

Total Lines 313
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
dl 0
loc 313
rs 8.6
c 0
b 0
f 0
wmc 37
lcom 1
cbo 1

18 Methods

Rating   Name   Duplication   Size   Complexity  
A getUserDateFormat() 0 4 1
A getUserDateTimeFormat() 0 4 1
A getUserTimeFormat() 0 4 1
A getTimeFormats() 0 7 1
B getDateFormats() 0 26 2
A getDateTimeFormats() 0 14 3
A getAllDateFormats() 0 4 1
A getAvailableFormats() 0 10 2
A getParserFormats() 0 11 1
A getTimestamp() 0 16 4
B getValidDate() 0 15 5
A withinDateRange() 0 4 2
A getHours() 0 6 1
A getIsoDate() 0 4 1
A getTimestampFromIsoFormat() 0 4 2
A removeTimeFromTimestamp() 0 4 1
A format() 0 16 4
A convert() 0 11 4
1
<?php
2
3
/*
4
 * This file is part of Jitamin.
5
 *
6
 * Copyright (C) Jitamin Team
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Jitamin\Foundation;
13
14
use DateTime;
15
16
/**
17
 * Date Parser.
18
 */
19
class DateParser extends Base
20
{
21
    const DATE_FORMAT = 'm/d/Y';
22
    const DATE_TIME_FORMAT = 'm/d/Y H:i';
23
    const TIME_FORMAT = 'H:i';
24
25
    /**
26
     * Get date format from settings.
27
     *
28
     * @return string
29
     */
30
    public function getUserDateFormat()
31
    {
32
        return $this->settingModel->get('application_date_format', self::DATE_FORMAT);
0 ignored issues
show
Documentation introduced by
The property settingModel does not exist on object<Jitamin\Foundation\DateParser>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
33
    }
34
35
    /**
36
     * Get date time format from settings.
37
     *
38
     * @return string
39
     */
40
    public function getUserDateTimeFormat()
41
    {
42
        return $this->settingModel->get('application_datetime_format', self::DATE_TIME_FORMAT);
0 ignored issues
show
Documentation introduced by
The property settingModel does not exist on object<Jitamin\Foundation\DateParser>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
43
    }
44
45
    /**
46
     * Get time format from settings.
47
     *
48
     * @return string
49
     */
50
    public function getUserTimeFormat()
51
    {
52
        return $this->settingModel->get('application_time_format', self::TIME_FORMAT);
0 ignored issues
show
Documentation introduced by
The property settingModel does not exist on object<Jitamin\Foundation\DateParser>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
53
    }
54
55
    /**
56
     * List of time formats.
57
     *
58
     * @return string[]
59
     */
60
    public function getTimeFormats()
61
    {
62
        return [
63
            'H:i',
64
            'g:i a',
65
        ];
66
    }
67
68
    /**
69
     * List of date formats.
70
     *
71
     * @param bool $iso
72
     *
73
     * @return string[]
74
     */
75
    public function getDateFormats($iso = false)
76
    {
77
        $formats = [
78
            $this->getUserDateFormat(),
79
        ];
80
81
        $isoFormats = [
82
            'Y-m-d',
83
            'Y_m_d',
84
        ];
85
86
        $userFormats = [
87
            'm/d/Y',
88
            'd/m/Y',
89
            'Y/m/d',
90
            'd.m.Y',
91
        ];
92
93
        if ($iso) {
94
            $formats = array_merge($formats, $isoFormats, $userFormats);
95
        } else {
96
            $formats = array_merge($formats, $userFormats);
97
        }
98
99
        return array_unique($formats);
100
    }
101
102
    /**
103
     * List of datetime formats.
104
     *
105
     * @param bool $iso
106
     *
107
     * @return string[]
108
     */
109
    public function getDateTimeFormats($iso = false)
110
    {
111
        $formats = [
112
            $this->getUserDateTimeFormat(),
113
        ];
114
115
        foreach ($this->getDateFormats($iso) as $date) {
116
            foreach ($this->getTimeFormats() as $time) {
117
                $formats[] = $date.' '.$time;
118
            }
119
        }
120
121
        return array_unique($formats);
122
    }
123
124
    /**
125
     * List of all date formats.
126
     *
127
     * @param bool $iso
128
     *
129
     * @return string[]
130
     */
131
    public function getAllDateFormats($iso = false)
132
    {
133
        return array_merge($this->getDateFormats($iso), $this->getDateTimeFormats($iso));
134
    }
135
136
    /**
137
     * Get available formats (visible in settings).
138
     *
139
     * @param array $formats
140
     *
141
     * @return array
142
     */
143
    public function getAvailableFormats(array $formats)
144
    {
145
        $values = [];
146
147
        foreach ($formats as $format) {
148
            $values[$format] = date($format).' ('.$format.')';
149
        }
150
151
        return $values;
152
    }
153
154
    /**
155
     * Get formats for date parsing.
156
     *
157
     * @return array
158
     */
159
    public function getParserFormats()
160
    {
161
        return [
162
            $this->getUserDateFormat(),
163
            'Y-m-d',
164
            'Y_m_d',
165
            $this->getUserDateTimeFormat(),
166
            'Y-m-d H:i',
167
            'Y_m_d H:i',
168
        ];
169
    }
170
171
    /**
172
     * Parse a date and return a unix timestamp, try different date formats.
173
     *
174
     * @param string $value Date to parse
175
     *
176
     * @return int
177
     */
178
    public function getTimestamp($value)
179
    {
180
        if (ctype_digit($value)) {
181
            return (int) $value;
182
        }
183
184
        foreach ($this->getParserFormats() as $format) {
185
            $timestamp = $this->getValidDate($value, $format);
186
187
            if ($timestamp !== 0) {
188
                return $timestamp;
189
            }
190
        }
191
192
        return 0;
193
    }
194
195
    /**
196
     * Return a timestamp if the given date format is correct otherwise return 0.
197
     *
198
     * @param string $value  Date to parse
199
     * @param string $format Date format
200
     *
201
     * @return int
202
     */
203
    private function getValidDate($value, $format)
204
    {
205
        $date = DateTime::createFromFormat($format, $value);
206
207
        if ($date !== false) {
208
            $errors = DateTime::getLastErrors();
209
            if ($errors['error_count'] === 0 && $errors['warning_count'] === 0) {
210
                $timestamp = $date->getTimestamp();
211
212
                return $timestamp > 0 ? $timestamp : 0;
213
            }
214
        }
215
216
        return 0;
217
    }
218
219
    /**
220
     * Return true if the date is within the date range.
221
     *
222
     * @param DateTime $date
223
     * @param DateTime $start
224
     * @param DateTime $end
225
     *
226
     * @return bool
227
     */
228
    public function withinDateRange(DateTime $date, DateTime $start, DateTime $end)
229
    {
230
        return $date >= $start && $date <= $end;
231
    }
232
233
    /**
234
     * Get the total number of hours between 2 datetime objects
235
     * Minutes are rounded to the nearest quarter.
236
     *
237
     * @param DateTime $d1
238
     * @param DateTime $d2
239
     *
240
     * @return float
241
     */
242
    public function getHours(DateTime $d1, DateTime $d2)
243
    {
244
        $seconds = abs($d1->getTimestamp() - $d2->getTimestamp());
245
246
        return round($seconds / 3600, 2);
247
    }
248
249
    /**
250
     * Get ISO-8601 date from user input.
251
     *
252
     * @param string $value Date to parse
253
     *
254
     * @return string
255
     */
256
    public function getIsoDate($value)
257
    {
258
        return date('Y-m-d', $this->getTimestamp($value));
259
    }
260
261
    /**
262
     * Get a timestamp from an ISO date format.
263
     *
264
     * @param string $value
265
     *
266
     * @return int
267
     */
268
    public function getTimestampFromIsoFormat($value)
269
    {
270
        return $this->removeTimeFromTimestamp(ctype_digit($value) ? $value : strtotime($value));
271
    }
272
273
    /**
274
     * Remove the time from a timestamp.
275
     *
276
     * @param int $timestamp
277
     *
278
     * @return int
279
     */
280
    public function removeTimeFromTimestamp($timestamp)
281
    {
282
        return mktime(0, 0, 0, date('m', $timestamp), date('d', $timestamp), date('Y', $timestamp));
283
    }
284
285
    /**
286
     * Format date (form display).
287
     *
288
     * @param array    $values Database values
289
     * @param string[] $fields Date fields
290
     * @param string   $format Date format
291
     *
292
     * @return array
293
     */
294
    public function format(array $values, array $fields, $format)
295
    {
296
        foreach ($fields as $field) {
297
            if (!empty($values[$field])) {
298
                if (!ctype_digit($values[$field])) {
299
                    $values[$field] = strtotime($values[$field]);
300
                }
301
302
                $values[$field] = date($format, $values[$field]);
303
            } else {
304
                $values[$field] = '';
305
            }
306
        }
307
308
        return $values;
309
    }
310
311
    /**
312
     * Convert date to timestamp.
313
     *
314
     * @param array    $values    Database values
315
     * @param string[] $fields    Date fields
316
     * @param bool     $keep_time Keep time or not
317
     *
318
     * @return array
319
     */
320
    public function convert(array $values, array $fields, $keep_time = false)
321
    {
322
        foreach ($fields as $field) {
323
            if (!empty($values[$field])) {
324
                $timestamp = $this->getTimestamp($values[$field]);
325
                $values[$field] = $keep_time ? $timestamp : $this->removeTimeFromTimestamp($timestamp);
326
            }
327
        }
328
329
        return $values;
330
    }
331
}
332