Passed
Branch 2.0.x (149bdc)
by Abdullah
02:48
created

TimeZoneService::getTimeDiff()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
c 2
b 0
f 0
nc 1
nop 1
dl 0
loc 5
rs 10
1
<?php
2
3
namespace Joy2362\PhpTimezone\Service;
4
5
use DateTime;
6
use Exception;
7
use DateTimeZone;
8
use Illuminate\Support\{Collection, Facades\Config, Str};
9
use Joy2362\PhpTimezone\Contract\TimeZoneManager;
10
11
class TimeZoneService implements TimeZoneManager
12
{
13
    /**
14
     * @var array
15
     */
16
    private array $regions = [
17
        'Africa' => DateTimeZone::AFRICA,
18
        'America' => DateTimeZone::AMERICA,
19
        'Antarctica' => DateTimeZone::ANTARCTICA,
20
        'Asia' => DateTimeZone::ASIA,
21
        'Atlantic' => DateTimeZone::ATLANTIC,
22
        'Australia' => DateTimeZone::AUSTRALIA,
23
        'Europe' => DateTimeZone::EUROPE,
24
        'Indian' => DateTimeZone::INDIAN,
25
        'Pacific' => DateTimeZone::PACIFIC,
26
    ];
27
28
    /**
29
     * @var array|string[]
30
     */
31
    private array $supportedTimeZone = ['GMT', 'UTC'];
32
33
    /**
34
     * @return array
35
     */
36
    public function getRegions(?string $search = ''): array
37
    {
38
        return $this->search(array_keys($this->regions), '', $search);
39
    }
40
41
    /**
42
     * @return array
43
     */
44
    public function getSupportedTimeZone(?string $search = ''): array
45
    {
46
        return $this->search($this->supportedTimeZone, '', $search);
47
    }
48
49
    /**
50
     * @return array
51
     */
52
    public function list(?string $search = ''): array
53
    {
54
        $list = [];
55
        foreach ($this->regions as $region) {
56
            $list = array_merge($list, $this->getTimeZoneList(DateTimeZone::listIdentifiers($region) ?? []));
57
        }
58
59
        return $this->search($list, 'label', $search);
60
    }
61
62
    /**
63
     * @return array
64
     */
65
    public function listWithoutLabel(?string $search = ''): array
66
    {
67
        $list = [];
68
        foreach ($this->regions as $region) {
69
            $list = array_merge($list, $this->getTimeZoneList(DateTimeZone::listIdentifiers($region) ?? [], 'value'));
70
        }
71
72
        return $this->search($list, '', $search);
73
    }
74
75
    /**
76
     * @return array
77
     */
78
    public function listWithoutValue(?string $search = ''): array
79
    {
80
        $list = [];
81
        foreach ($this->regions as $region) {
82
            $list = array_merge($list, $this->getTimeZoneList(DateTimeZone::listIdentifiers($region) ?? [], 'label'));
83
        }
84
85
        return $this->search($list, '', $search);
86
    }
87
88
    public function listByRegion(string $region, ?string $search = ''): array
89
    {
90
        if (!array_key_exists(ucfirst($region), $this->regions)) {
91
            return [];
92
        }
93
94
        $list = $this->getTimeZoneList(DateTimeZone::listIdentifiers($this->regions[ucfirst($region)]) ?? []);
95
        return $this->search($list, 'label', $search);
96
    }
97
98
    /**
99
     * @param string $label
100
     * @return string
101
     */
102
    public function getValueFromLabel(string $label): string
103
    {
104
        $zone = explode(') ', $label);
105
        return  isset($zone[1]) ? str_replace(' ', '_', $zone[1]) : '';
106
    }
107
108
    /**
109
     * @param $value
110
     * @return string
111
     */
112
    public function getLabelFromValue(string $value): string
113
    {
114
        return $this->getLabel($value);
115
    }
116
117
    /**
118
     * @param $timezone
119
     * @return string
120
     */
121
    private function getLabel(string $timezone): string
122
    {
123
        try {
124
            $time = new DateTime('', new DateTimeZone(ucfirst($timezone)));
125
            $time_diff = $this->getTimeDiff($time);
126
            $zone = $this->getZone($time);
127
            $defaultTimeZone = Config::get('Timezone.DEFAULT_TIME_ZONE', 'GMT');
128
            $defaultTimeZone = in_array($defaultTimeZone, $this->supportedTimeZone) ? $defaultTimeZone : $this->supportedTimeZone[0];
129
            return "({$defaultTimeZone} {$time_diff}) {$zone}";
130
        } catch (Exception $ex) {
131
            return '';
132
        }
133
    }
134
135
    /**
136
     * @param $time
137
     * @return string
138
     */
139
    private function getTimeDiff(DateTime $time): string
140
    {
141
        $time_diff_symbol = Config::get('Timezone.TIME_DIFF_SYMBOL', '.');
142
        $str_time_diff = $time->format('p');
143
        return str_replace(':', $time_diff_symbol, $str_time_diff);
144
    }
145
146
    /**
147
    * @param $time
148
    * @return string
149
    */
150
    private function getZone(DateTime $time): string
151
    {
152
        return str_replace('_', ' ', $time->format('e'));
153
    }
154
155
    /**
156
     * @param array $timezones
157
     * @param bool $isLabel
158
     * @param bool $isValue
159
     * @return array
160
    */
161
    private function getTimeZoneList(array $timezones, string $type = 'list'): array
162
    {
163
        $label = Config::get('Timezone.LABEL_FIELD_NAME', 'label');
164
        $value = Config::get('Timezone.VALUE_FIELD_NAME', 'value');
165
166
        $data = [];
167
168
        foreach ($timezones as $timezone) {
169
170
            switch ($type) {
171
                case 'label':
172
                    $data[] = $this->getLabel($timezone);
173
                    break;
174
175
                case 'value':
176
                    $data[] = $timezone;
177
                    break;
178
179
                default:
180
                    $zone = [
181
                        "{$label}" => $this->getLabel($timezone),
182
                        "{$value}" => $timezone,
183
                    ];
184
                    $data[] = $zone;
185
                    break;
186
            }
187
        }
188
        return $data;
189
    }
190
191
    /**
192
     * @param array $list
193
     * @param ?string $search
194
     * @return array
195
    */
196
    private function search(array $list, ?string $key = '', ?string $search): array 
197
    {
198
        return collect($list)->when(!empty($search), function (Collection $collection) use($search, $key){
199
            return $collection->filter(fn($item) => Str::contains(Str::lower(!empty($key) ? $item[$key] :$item), Str::lower($search)));
200
        })->values()->toArray();
201
    }
202
}