├── .gitignore
├── src
├── Validator
│ ├── ValidatorInterface.php
│ ├── ValidIntegerValidator.php
│ ├── LeapYearValidator.php
│ └── DateValidator.php
├── Holiday
│ ├── HolidayInterface.php
│ ├── Christmas.php
│ └── Easter.php
├── Exception
│ └── InvalidDateException.php
├── Converter
│ ├── Converter.php
│ ├── ToJdnConverter.php
│ └── FromJdnConverter.php
├── Operations
│ ├── Initiator.php
│ ├── Processor.php
│ └── Formatter.php
├── DateTimeFactory.php
├── DateTime.php
└── Constants.php
├── phpunit.xml.dist
├── tests
├── Exception
│ └── InvalidDateExceptionTest.php
├── Validator
│ ├── LeapYearValidatorTest.php
│ └── DateValidatorTest.php
├── Converter
│ ├── FromJdnConverterTest.php
│ ├── ToJdnConverterTest.php
│ └── ConverterTest.php
├── Holiday
│ ├── ChristmasTest.php
│ └── EasterTest.php
└── DateTimeTest.php
├── composer.json
├── .github
└── workflows
│ └── tests.yml
├── LICENSE
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | composer.lock
2 | .phpunit.result.cache
3 | /vendor
4 |
--------------------------------------------------------------------------------
/src/Validator/ValidatorInterface.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
10 | tests
11 |
12 |
13 |
14 |
15 |
16 | src
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/tests/Exception/InvalidDateExceptionTest.php:
--------------------------------------------------------------------------------
1 | expectExceptionMessage('Invalid date was given');
13 | $this->expectException(InvalidDateException::class);
14 |
15 | throw new InvalidDateException();
16 | }
17 |
18 | public function test_by_catching_the_exception()
19 | {
20 | try {
21 | throw new InvalidDateException();
22 | } catch (\Exception $e) {
23 | $this->assertTrue($e instanceof InvalidDateException);
24 | $this->assertEquals($e->getMessage(), 'Invalid date was given');
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/Validator/LeapYearValidator.php:
--------------------------------------------------------------------------------
1 | year = $year;
23 | }
24 |
25 | /**
26 | * @return bool true if valid
27 | */
28 | public function isValid()
29 | {
30 | return
31 | $this->isValidInteger($this->year) &&
32 | $this->isValidLeapYear($this->year);
33 | }
34 |
35 | /**
36 | * @param $year int
37 | *
38 | * @return bool true if valid
39 | */
40 | protected function isValidLeapYear($year)
41 | {
42 | return ($year + 1) % 4 === 0;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/tests/Validator/LeapYearValidatorTest.php:
--------------------------------------------------------------------------------
1 | assertEquals($expected, $validator->isValid());
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/tests/Converter/FromJdnConverterTest.php:
--------------------------------------------------------------------------------
1 | expectException(TypeError::class);
18 |
19 | new FromJdnConverter($jdn);
20 | }
21 |
22 | /**
23 | * @dataProvider validJDNDataProvider
24 | *
25 | * @param $jdn
26 | * @param $year
27 | * @param $month
28 | * @param $day
29 | */
30 | public function test_conversion_from_jdn($jdn, $year, $month, $day)
31 | {
32 | $converter = new FromJdnConverter($jdn);
33 |
34 | $this->assertEquals($day, $converter->getDay());
35 | $this->assertEquals($month, $converter->getMonth());
36 | $this->assertEquals($year, $converter->getYear());
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "andegna/calender",
3 | "type": "library",
4 | "description": "If you ever want to convert Ethiopian Calender to any other calender system (like the Gregorian Calender) this is the right package for you. And by the way it also support Amharic date formatting and much much more.",
5 | "keywords": ["ethiopian", "date", "calender", "JDN"],
6 | "license": "MIT",
7 | "support": {
8 | "issues": "https://github.com/andegna/calender/issues",
9 | "source": "https://github.com/andegna/calender"
10 | },
11 | "authors": [
12 | {
13 | "name": "Sam As End",
14 | "email": "4sam21@gmail.com"
15 | }
16 | ],
17 | "require": {
18 | "php": ">=7.3",
19 | "geezify/geezify-php": "^1.2"
20 | },
21 | "require-dev": {
22 | "phpunit/phpunit": "^9.5"
23 | },
24 | "autoload": {
25 | "psr-4": {
26 | "Andegna\\": "src/",
27 | "Andegna\\PHPUnit\\": "tests/"
28 | }
29 | },
30 | "scripts": {
31 | "test": "phpunit --coverage-clover=coverage.clover"
32 | },
33 | "extra": {
34 | "branch-alias": {
35 | "develop": "2.4-dev"
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/.github/workflows/tests.yml:
--------------------------------------------------------------------------------
1 | name: Tests
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 | pull_request:
7 | branches: [ master ]
8 |
9 | jobs:
10 | build:
11 |
12 | runs-on: ubuntu-latest
13 |
14 | steps:
15 | - uses: actions/checkout@v2
16 |
17 | - name: Validate composer.json and composer.lock
18 | run: composer validate --strict
19 |
20 | - name: Cache Composer packages
21 | id: composer-cache
22 | uses: actions/cache@v2
23 | with:
24 | path: vendor
25 | key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
26 | restore-keys: |
27 | ${{ runner.os }}-php-
28 |
29 | - name: Install dependencies
30 | run: composer install --prefer-dist --no-progress
31 |
32 | - name: Run test suite
33 | env:
34 | XDEBUG_MODE: coverage
35 | run: composer run-script test
36 |
37 | - name: Upload Scrutinizer coverage
38 | uses: sudo-bot/action-scrutinizer@latest
39 | with:
40 | cli-args: "--format=php-clover coverage.clover"
41 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Samson Endale
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/Holiday/Christmas.php:
--------------------------------------------------------------------------------
1 | dateTimeZone = $dateTimeZone;
27 | }
28 |
29 | /**
30 | * {@inheritdoc}
31 | */
32 | public function get(int $year)
33 | {
34 | $day = 29;
35 |
36 | if ($this->wasAfterALeapYear($year)) {
37 | $day = 28;
38 | }
39 |
40 | return DateTimeFactory::of($year, self::TAHISAS, $day, 0, 0, 0, $this->dateTimeZone);
41 | }
42 |
43 | private function wasAfterALeapYear(int $year): bool
44 | {
45 | $previous = $year - 1;
46 |
47 | return (new LeapYearValidator($previous))->isValid();
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/Converter/Converter.php:
--------------------------------------------------------------------------------
1 | day;
37 | }
38 |
39 | /**
40 | * Get the month.
41 | *
42 | * @return int
43 | */
44 | public function getMonth(): int
45 | {
46 | return $this->month;
47 | }
48 |
49 | /**
50 | * Get the year.
51 | *
52 | * @return int
53 | */
54 | public function getYear(): int
55 | {
56 | return $this->year;
57 | }
58 |
59 | /**
60 | * Get the JDN.
61 | *
62 | * @return int
63 | */
64 | public function getJdn(): int
65 | {
66 | return $this->jdn;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/tests/Holiday/ChristmasTest.php:
--------------------------------------------------------------------------------
1 | christmas = new Christmas(new \DateTimeZone('Africa/Addis_Ababa'));
20 | }
21 |
22 | /**
23 | * Eastern Orthodox churches christmas dates.
24 | *
25 | * @return array
26 | */
27 | public function christmasDatesDataProvider()
28 | {
29 | return [
30 | [2010, 29],
31 | [2011, 29],
32 | [2012, 28],
33 | [2013, 29],
34 | [2014, 29],
35 | [2015, 29],
36 | [2016, 28],
37 | [2017, 29],
38 | ];
39 | }
40 |
41 | /**
42 | * @dataProvider christmasDatesDataProvider
43 | *
44 | * @param $year
45 | * @param $day
46 | */
47 | public function test_christmas_date($year, $day)
48 | {
49 | $ethiopian = $this->christmas->get($year);
50 |
51 | $this->assertEquals($year, $ethiopian->getYear());
52 | $this->assertEquals(4, $ethiopian->getMonth());
53 | $this->assertEquals($day, $ethiopian->getDay());
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/tests/Converter/ToJdnConverterTest.php:
--------------------------------------------------------------------------------
1 | expectException(TypeError::class);
22 |
23 | new ToJdnConverter($day, $month, $year);
24 | }
25 |
26 | /**
27 | * @dataProvider illegalDateDataProvider
28 | *
29 | * @param $month
30 | * @param $day
31 | * @param $year
32 | * @param $ignore
33 | */
34 | public function test_me_too($month, $day, $year, $ignore)
35 | {
36 | $this->expectException(InvalidDateException::class);
37 |
38 | new ToJdnConverter($day, $month, $year);
39 | }
40 |
41 | /**
42 | * @dataProvider validJDNDataProvider
43 | *
44 | * @param $jdn
45 | * @param $year
46 | * @param $month
47 | * @param $day
48 | */
49 | public function test_conversion_to_jdn($jdn, $year, $month, $day)
50 | {
51 | $converter = new ToJdnConverter($day, $month, $year);
52 |
53 | $this->assertEquals($jdn, $converter->getJdn());
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/Holiday/Easter.php:
--------------------------------------------------------------------------------
1 | dateTimeZone = $dateTimeZone;
25 | }
26 |
27 | /**
28 | * {@inheritdoc}
29 | */
30 | public function get(int $year)
31 | {
32 | // convert the Ethiopian year to a Julian year
33 | // ሚያዝያ 1 is just a random day after the Gregorian new year
34 | $julian_year = (int) DateTimeFactory::of($year, 8, 1)
35 | ->toGregorian()->format('Y');
36 |
37 | // get the number of days from vernal equinox to the Easter in the given Julian year
38 | $days_after = easter_days($julian_year, CAL_EASTER_ALWAYS_JULIAN);
39 |
40 | // get the JDN of vernal equinox (March 21) in the given Julian year
41 | $jdn = juliantojd(3, 21, $julian_year);
42 |
43 | // add the number of days to Easter
44 | $jdn += $days_after;
45 |
46 | // create a Ethiopian Date to JDN converter
47 | $con = new FromJdnConverter($jdn);
48 |
49 | // create an Ethiopian date from the converter
50 | return DateTimeFactory::of(
51 | $con->getYear(),
52 | $con->getMonth(),
53 | $con->getDay(),
54 | 0,
55 | 0,
56 | 0,
57 | $this->dateTimeZone
58 | );
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/Converter/ToJdnConverter.php:
--------------------------------------------------------------------------------
1 | set($day, $month, $year);
25 | }
26 |
27 | /**
28 | * Set the date for processing.
29 | *
30 | * @param $day
31 | * @param $month
32 | * @param $year
33 | *
34 | * @throws \Andegna\Exception\InvalidDateException
35 | *
36 | * @return $this
37 | */
38 | public function set(int $day, int $month, int $year)
39 | {
40 | $validator = new DateValidator($day, $month, $year);
41 |
42 | if (!$validator->isValid()) {
43 | throw new InvalidDateException();
44 | }
45 |
46 | $this->day = $day;
47 | $this->month = $month;
48 | $this->year = $year;
49 |
50 | $this->jdn = (int) static::process($day, $month, $year);
51 |
52 | return $this;
53 | }
54 |
55 | /**
56 | * @param $day
57 | * @param $month
58 | * @param $year
59 | *
60 | * @return int
61 | */
62 | protected static function process($day, $month, $year)
63 | {
64 | return
65 | (1723856 + 365) +
66 | 365 * ($year - 1) +
67 | (int) ($year / 4) +
68 | 30 * $month +
69 | $day - 31;
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/Converter/FromJdnConverter.php:
--------------------------------------------------------------------------------
1 | set($jdn);
22 | }
23 |
24 | /**
25 | * Set the JDN for processing.
26 | *
27 | * @param $jdn
28 | *
29 | * @throws \Andegna\Exception\InvalidDateException
30 | *
31 | * @return $this
32 | */
33 | public function set(int $jdn)
34 | {
35 | if (!$this->isValidInteger($jdn)) {
36 | throw new InvalidDateException();
37 | }
38 |
39 | $this->jdn = $jdn;
40 |
41 | $date = static::process($jdn);
42 |
43 | return $this->setDate($date);
44 | }
45 |
46 | /**
47 | * @param $jdn integer
48 | *
49 | * @return array
50 | */
51 | protected static function process(int $jdn): array
52 | {
53 | $r = (($jdn - 1723856) % 1461);
54 | $n = ($r % 365) + 365 * (int) ($r / 1460);
55 |
56 | $year = 4 * (int) (($jdn - 1723856) / 1461) +
57 | (int) ($r / 365) - (int) ($r / 1460);
58 | $month = (int) ($n / 30) + 1;
59 | $day = ($n % 30) + 1;
60 |
61 | return compact('day', 'month', 'year');
62 | }
63 |
64 | /**
65 | * @param $date array
66 | *
67 | * @return $this|Converter
68 | */
69 | protected function setDate(array $date): Converter
70 | {
71 | $this->day = $date['day'];
72 | $this->month = $date['month'];
73 | $this->year = $date['year'];
74 |
75 | return $this;
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/tests/Validator/DateValidatorTest.php:
--------------------------------------------------------------------------------
1 | assertEquals($expected, $validator->isValid());
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/Validator/DateValidator.php:
--------------------------------------------------------------------------------
1 | day = $day;
43 | $this->month = $month;
44 | $this->year = $year;
45 | }
46 |
47 | /**
48 | * validate the ethiopian date.
49 | *
50 | * @return bool true if valid
51 | */
52 | public function isValid()
53 | {
54 | $validators = [
55 | 'isDateValuesIntegers',
56 | 'isValidDayRange',
57 | 'isValidMonthRange',
58 | 'isValidPagumeDayRange',
59 | 'isValidLeapDay',
60 | ];
61 |
62 | return array_reduce($validators, function ($result, $validator) {
63 | return $result && $this->{$validator}();
64 | }, true);
65 | }
66 |
67 | /**
68 | * @return bool
69 | */
70 | protected function isValidDayRange()
71 | {
72 | return $this->day >= self::FIRST_DAY &&
73 | $this->day <= self::LAST_DAY;
74 | }
75 |
76 | /**
77 | * @return bool
78 | */
79 | protected function isValidMonthRange()
80 | {
81 | return $this->month >= self::FIRST_MONTH &&
82 | $this->month <= self::LAST_MONTH;
83 | }
84 |
85 | /**
86 | * @return bool
87 | */
88 | protected function isValidPagumeDayRange()
89 | {
90 | if ($this->month === self::LAST_MONTH) {
91 | return $this->day <= self::PAGUME_LEAP_YEAR_LAST_DAY;
92 | }
93 |
94 | return true;
95 | }
96 |
97 | /**
98 | * @return bool
99 | */
100 | protected function isValidLeapDay()
101 | {
102 | if ($this->month === self::LAST_MONTH &&
103 | $this->day === self::PAGUME_LEAP_YEAR_LAST_DAY
104 | ) {
105 | return (new LeapYearValidator($this->year))->isValid();
106 | }
107 |
108 | return true;
109 | }
110 |
111 | /**
112 | * @return bool
113 | */
114 | protected function isDateValuesIntegers()
115 | {
116 | return $this->isValidInteger($this->day, $this->month, $this->year);
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/tests/Holiday/EasterTest.php:
--------------------------------------------------------------------------------
1 | easter = new Easter(new \DateTimeZone('Africa/Addis_Ababa'));
27 | }
28 |
29 | /**
30 | * Eastern Orthodox churches easter dates.
31 | *
32 | * @link https://en.wikipedia.org/wiki/Computus
33 | *
34 | * @return array
35 | */
36 | public function easterDatesDataProvider()
37 | {
38 | return [
39 | [1997, 'April 27'],
40 | [1998, 'April 19'],
41 | [1999, 'April 11'],
42 | [2000, 'April 30'],
43 | [2001, 'April 15'],
44 | [2002, 'May 5'],
45 | [2003, 'April 27'],
46 | [2004, 'April 11'],
47 | [2005, 'May 1'],
48 | [2006, 'April 23'],
49 | [2007, 'April 8'],
50 | [2008, 'April 27'],
51 | [2009, 'April 19'],
52 | [2010, 'April 4'],
53 | [2011, 'April 24'],
54 | [2012, 'April 15'],
55 | [2013, 'May 5'],
56 | [2014, 'April 20'],
57 | [2015, 'April 12'],
58 | [2016, 'May 1'],
59 | [2017, 'April 16'],
60 | [2018, 'April 8'],
61 | [2019, 'April 28'],
62 | [2020, 'April 19'],
63 | [2021, 'May 2'],
64 | [2022, 'April 24'],
65 | [2023, 'April 16'],
66 | [2024, 'May 5'],
67 | [2025, 'April 20'],
68 | [2026, 'April 12'],
69 | [2027, 'May 2'],
70 | [2028, 'April 16'],
71 | [2029, 'April 8'],
72 | [2030, 'April 28'],
73 | [2031, 'April 13'],
74 | [2032, 'May 2'],
75 | [2033, 'April 24'],
76 | [2034, 'April 9'],
77 | [2035, 'April 29'],
78 | [2036, 'April 20'],
79 | [2037, 'April 5'],
80 | ];
81 | }
82 |
83 | /**
84 | * @dataProvider easterDatesDataProvider
85 | *
86 | * @param $year
87 | * @param $day_month
88 | */
89 | public function test_easter_date($year, $day_month)
90 | {
91 | $gregorian = \DateTime::createFromFormat('F j Y', "$day_month $year");
92 |
93 | $expected = new DateTime($gregorian);
94 |
95 | $ethiopian = $this->easter->get($expected->getYear());
96 |
97 | $this->assertEquals($expected->getYear(), $ethiopian->getYear());
98 | $this->assertEquals($expected->getMonth(), $ethiopian->getMonth());
99 | $this->assertEquals($expected->getDay(), $ethiopian->getDay());
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/src/Operations/Initiator.php:
--------------------------------------------------------------------------------
1 | getJdnFromBase($this->dateTime);
24 |
25 | $converter = new FromJdnConverter($jdn);
26 |
27 | $this->setDateFromConverter($converter);
28 | $this->cacheTimestamp();
29 | $this->computeFields();
30 | }
31 |
32 | /**
33 | * Return the JDN of the given gregorian date time.
34 | *
35 | * @param GregorianDateTime $dateTime
36 | *
37 | * @return int
38 | */
39 | protected function getJdnFromBase(GregorianDateTime $dateTime): int
40 | {
41 | $year = $dateTime->format('Y');
42 | $month = $dateTime->format('m');
43 | $day = $dateTime->format('d');
44 |
45 | return gregoriantojd($month, $day, $year);
46 | }
47 |
48 | /**
49 | * Set the converted year, month and day from the given converter.
50 | *
51 | * @param Converter $converter
52 | *
53 | * @return void
54 | */
55 | protected function setDateFromConverter(Converter $converter)
56 | {
57 | $this->year = $converter->getYear();
58 | $this->month = $converter->getMonth();
59 | $this->day = $converter->getDay();
60 | }
61 |
62 | /**
63 | * Set the timestamp field.
64 | */
65 | protected function cacheTimestamp()
66 | {
67 | $this->timestamp = $this->dateTime->getTimestamp();
68 | }
69 |
70 | /**
71 | * Computer the available properties.
72 | *
73 | * @return void
74 | */
75 | protected function computeFields()
76 | {
77 | $this->computeLeapYear();
78 | $this->computeDayOfYear();
79 | $this->computeDaysInMonth();
80 | $this->cacheDayOfWeek();
81 | }
82 |
83 | /**
84 | * Compute the leapYear property.
85 | *
86 | * @return void
87 | */
88 | protected function computeLeapYear()
89 | {
90 | $leapYear = new LeapYearValidator($this->year);
91 |
92 | $this->leapYear = $leapYear->isValid();
93 | }
94 |
95 | /**
96 | * Compute the dayOfYear property.
97 | *
98 | * @return void
99 | */
100 | protected function computeDayOfYear()
101 | {
102 | $this->dayOfYear = ($this->month - 1) * 30 + $this->day;
103 | }
104 |
105 | /**
106 | * Compute the daysInMonth property.
107 | *
108 | * @return void
109 | */
110 | protected function computeDaysInMonth()
111 | {
112 | $this->daysInMonth = $this->month === 13 ? ($this->leapYear ? 6 : 5) : 30;
113 | }
114 |
115 | /**
116 | * cache the dayOfWeek property.
117 | *
118 | * @return void
119 | */
120 | protected function cacheDayOfWeek()
121 | {
122 | $this->dayOfWeek = (int) $this->dateTime->format('N');
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/tests/Converter/ConverterTest.php:
--------------------------------------------------------------------------------
1 | getJdn();
73 |
74 | // The gregorian date in "month/day/year" format
75 | $gregorian = jdtogregorian($jdn);
76 |
77 | $dateTimeZone = self::checkForDateTimeZone($dateTimeZone);
78 |
79 | $base = new GregorianDateTime(
80 | "$gregorian $hour:$minute:$second",
81 | $dateTimeZone
82 | );
83 |
84 | return new DateTime($base);
85 | }
86 |
87 | /**
88 | * @param int $timestamp timestamp like @see time()
89 | * @param DateTimeZone|null $dateTimeZone the timezone
90 | *
91 | * @return DateTime the datetime u wanted
92 | */
93 | public static function fromTimestamp($timestamp, DateTimeZone $dateTimeZone = null)
94 | {
95 | $base = new GregorianDateTime(
96 | date('Y-m-d H:i:s', $timestamp),
97 | self::checkForDateTimeZone($dateTimeZone)
98 | );
99 |
100 | return new DateTime($base);
101 | }
102 |
103 | /**
104 | * Just for convenience.
105 | *
106 | * @param GregorianDateTime $gregorian
107 | *
108 | * @return DateTime the datetime u wanted
109 | */
110 | public static function fromDateTime(GregorianDateTime $gregorian)
111 | {
112 | return new DateTime($gregorian);
113 | }
114 |
115 | /**
116 | * Just for convenience.
117 | *
118 | * @param Converter $con
119 | * @param DateTimeZone|null $dateTimeZone
120 | *
121 | * @return DateTime the datetime u wanted
122 | */
123 | public static function fromConverter(Converter $con, DateTimeZone $dateTimeZone = null)
124 | {
125 | return static::of(
126 | $con->getYear(),
127 | $con->getMonth(),
128 | $con->getDay(),
129 | 0,
130 | 0,
131 | 0,
132 | $dateTimeZone
133 | );
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/src/Operations/Processor.php:
--------------------------------------------------------------------------------
1 |
12 | * works on dateTime property.
13 | */
14 | trait Processor
15 | {
16 | /**
17 | * @param mixed $dateTime
18 | *
19 | * @return mixed
20 | */
21 | protected function fixForChaining($dateTime = false)
22 | {
23 | if ($dateTime === false) {
24 | return $dateTime;
25 | }
26 |
27 | $this->updateComputedFields();
28 |
29 | return $this;
30 | }
31 |
32 | /**
33 | * Adds an amount of days, months, years, hours, minutes and seconds to a DateTime object.
34 | *
35 | * @param DateInterval $interval
36 | *
37 | * @return DateTime|bool
38 | */
39 | public function add(DateInterval $interval)
40 | {
41 | return $this->fixForChaining($this->dateTime->add($interval));
42 | }
43 |
44 | /**
45 | * Subtracts an amount of days, months, years, hours, minutes and seconds from a DateTime object.
46 | *
47 | * @param DateInterval $interval
48 | *
49 | * @return DateTime|bool
50 | */
51 | public function sub(DateInterval $interval)
52 | {
53 | return$this->fixForChaining($this->dateTime->sub($interval));
54 | }
55 |
56 | /**
57 | * Alters the timestamp.
58 | *
59 | * @param $modify
60 | *
61 | * @return DateTime|bool
62 | */
63 | public function modify($modify)
64 | {
65 | return $this->fixForChaining($this->dateTime->modify($modify));
66 | }
67 |
68 | /**
69 | * Returns the difference between two DateTime objects.
70 | *
71 | * @param $datetime
72 | * @param bool $absolute
73 | *
74 | * @return DateInterval
75 | */
76 | public function diff($datetime, $absolute = false)
77 | {
78 | if ($datetime instanceof DateTime) {
79 | return $this->dateTime->diff($datetime->toGregorian(), $absolute);
80 | }
81 |
82 | return $this->dateTime->diff($datetime, $absolute);
83 | }
84 |
85 | /**
86 | * Sets the date.
87 | *
88 | * @param $year
89 | * @param $month
90 | * @param $day
91 | *
92 | * @return DateTime
93 | */
94 | public function setDate($year, $month, $day)
95 | {
96 | $jdn = (new ToJdnConverter($day, $month, $year))->getJdn();
97 |
98 | $gregorian = jdtogregorian($jdn);
99 |
100 | list($month, $day, $year) = explode('/', $gregorian);
101 |
102 | $this->fixForChaining($this->dateTime->setDate((int) $year, (int) $month, (int) $day));
103 | }
104 |
105 | /**
106 | * Sets the time.
107 | *
108 | * @param $hour
109 | * @param $minute
110 | * @param int $second
111 | *
112 | * @return DateTime
113 | */
114 | public function setTime($hour, $minute, $second = 0)
115 | {
116 | return $this->fixForChaining($this->dateTime->setTime($hour, $minute, $second));
117 | }
118 |
119 | /**
120 | * Sets the date and time based on an Unix timestamp.
121 | *
122 | * @param $unixtimestamp
123 | *
124 | * @return DateTime
125 | */
126 | public function setTimestamp($unixtimestamp)
127 | {
128 | return $this->fixForChaining($this->dateTime->setTimestamp($unixtimestamp));
129 | }
130 |
131 | /**
132 | * Sets the time zone for the DateTime object.
133 | *
134 | * @param $timezone
135 | *
136 | * @return DateTime
137 | */
138 | public function setTimezone($timezone)
139 | {
140 | return $this->fixForChaining($this->dateTime->setTimezone($timezone));
141 | }
142 |
143 | /**
144 | * Returns the timezone offset.
145 | *
146 | * @return int
147 | */
148 | public function getOffset()
149 | {
150 | return $this->dateTime->getOffset();
151 | }
152 |
153 | /**
154 | * Return time zone relative to given DateTime.
155 | *
156 | * @return DateTimeZone
157 | */
158 | public function getTimezone()
159 | {
160 | return $this->dateTime->getTimezone();
161 | }
162 |
163 | /**
164 | * The __wakeup handler.
165 | */
166 | public function __wakeup()
167 | {
168 | return $this->dateTime->__wakeup();
169 | }
170 | }
171 |
--------------------------------------------------------------------------------
/src/DateTime.php:
--------------------------------------------------------------------------------
1 | year;
49 | }
50 |
51 | /**
52 | * Returns the Ethiopian Month.
53 | *
54 | * @return int month
55 | */
56 | public function getMonth()
57 | {
58 | return $this->month;
59 | }
60 |
61 | /**
62 | * Returns the Ethiopian Day.
63 | *
64 | * @return int day
65 | */
66 | public function getDay()
67 | {
68 | return $this->day;
69 | }
70 |
71 | /**
72 | * Returns true if the Year is a leap.
73 | *
74 | * @return bool leap year
75 | */
76 | public function isLeapYear()
77 | {
78 | return $this->leapYear;
79 | }
80 |
81 | /**
82 | * Returns the day Of the Year.
83 | *
84 | * Day of the year is the number of days(inclusive)
85 | * have passed since the new year
86 | *
87 | * Eg. 'ኅዳር 29' day of the year is 89
88 | *
89 | * @return int day Of the Year
90 | */
91 | public function getDayOfYear()
92 | {
93 | return $this->dayOfYear;
94 | }
95 |
96 | /**
97 | * Returns number of days in the given year.
98 | *
99 | * It's 30 except 'ጳጉሜን'
100 | *
101 | * @return int days in the month
102 | */
103 | public function getDaysInMonth()
104 | {
105 | return $this->daysInMonth;
106 | }
107 |
108 | /**
109 | * Returns the Hour.
110 | *
111 | * @return int hour
112 | */
113 | public function getHour()
114 | {
115 | return (int) $this->dateTime->format('G');
116 | }
117 |
118 | /**
119 | * Returns the Minute.
120 | *
121 | * @return int minute
122 | */
123 | public function getMinute()
124 | {
125 | return (int) $this->dateTime->format('i');
126 | }
127 |
128 | /**
129 | * Returns the Second.
130 | *
131 | * @return int second
132 | */
133 | public function getSecond()
134 | {
135 | return (int) $this->dateTime->format('s');
136 | }
137 |
138 | /**
139 | * Returns the Micro.
140 | *
141 | * @return int micro
142 | */
143 | public function getMicro()
144 | {
145 | return (int) $this->dateTime->format('u');
146 | }
147 |
148 | /**
149 | * Returns the Day of the week.
150 | *
151 | * 1 (for ሰኞ) through 7 (for እሑድ)
152 | *
153 | * @return int day of the week
154 | */
155 | public function getDayOfWeek()
156 | {
157 | return (int) $this->dateTime->format('N');
158 | }
159 |
160 | /**
161 | * Returns the Timestamp.
162 | *
163 | * @see time()
164 | *
165 | * @return int timestamp
166 | */
167 | public function getTimestamp()
168 | {
169 | return (int) $this->dateTime->format('U');
170 | }
171 |
172 | /**
173 | * DateTime constructor.
174 | *
175 | * @param GregorianDateTime|null $dateTime
176 | */
177 | public function __construct(GregorianDateTime $dateTime = null)
178 | {
179 | if (null === $dateTime) {
180 | $this->dateTime = new GregorianDateTime('now');
181 | } else {
182 | $this->dateTime = $dateTime;
183 | }
184 |
185 | $this->updateComputedFields();
186 | }
187 |
188 | /**
189 | * Return the clone of the base gregorian datetime.
190 | *
191 | * @return GregorianDateTime
192 | */
193 | public function toGregorian()
194 | {
195 | return clone $this->dateTime;
196 | }
197 | }
198 |
--------------------------------------------------------------------------------
/tests/DateTimeTest.php:
--------------------------------------------------------------------------------
1 | dateTime = DateTimeFactory::of(1986, 3, 21);
29 | $this->otherDateTime = new DateTime($this->dateTime->toGregorian()->add(new \DateInterval('P2Y4DT6H8M')));
30 | $this->yetAnotherDateTime = DateTimeFactory::of(2000, 1, 1, 0, 0, 0, new \DateTimeZone('America/Los_Angeles'))->sub(new \DateInterval('PT1H'));
31 | }
32 |
33 | public function test_my_birth_day()
34 | {
35 | $this->assertEquals(1986, $this->dateTime->getYear());
36 | $this->assertEquals(3, $this->dateTime->getMonth());
37 | $this->assertEquals(21, $this->dateTime->getDay());
38 |
39 | $this->assertEquals(81, $this->dateTime->getDayOfYear());
40 | $this->assertEquals(30, $this->dateTime->getDaysInMonth());
41 | $this->assertEquals(false, $this->dateTime->isLeapYear());
42 |
43 | $this->assertEquals(2, $this->dateTime->getDayOfWeek());
44 | $this->assertEquals(754606800, $this->dateTime->getTimestamp());
45 | $this->assertEquals(10800, $this->dateTime->getOffset());
46 | $this->assertEquals('Africa/Addis_Ababa', $this->dateTime->getTimezone()->getName());
47 |
48 | $this->assertEquals(
49 | 'ማክሰኞ, 21-ኅዳ-1986 00:00:00 የምስራቅ አፍሪካ ሰዓት (አዲስ አበባ)',
50 | $this->dateTime->format(DATE_COOKIE)
51 | );
52 |
53 | $this->assertEquals(
54 | 'ማክሰኞ፣ ኅዳር 21 ቀን 00:00:00 እኩለ፡ሌሊት የምስራቅ አፍሪካ ሰዓት (አዲስ አበባ) 1986 ዓ/ም',
55 | $this->dateTime->format(Constants::DATE_ETHIOPIAN)
56 | );
57 |
58 | $this->assertEquals(
59 | 'ሰኞ፣ ኅዳር 24 ቀን (ተክለ፡ሐይማኖት) 06:08:00 ጡዋት የምስራቅ አፍሪካ ሰዓት (አዲስ አበባ) 1988 (ዮሐንስ) ዓ/ም',
60 | $this->otherDateTime->format(Constants::DATE_ETHIOPIAN_ORTHODOX)
61 | );
62 |
63 | $this->assertEquals(
64 | 'ማክሰኞ, 21-ኅዳ-1986 00:00:00 የምስራቅ አፍሪካ ሰዓት (አዲስ አበባ)',
65 | $this->dateTime->format(DATE_COOKIE)
66 | );
67 |
68 | $this->assertEquals(
69 | 'ማክሰኞ፣ ጳጉሜን ፮ ቀን (ኢያሱስ) 23:00:00 እኩለ፡ሌሊት የፓስፊክ ሰዓት አቆጣጠር (ሎስ አንጀለስ) ፲፱፻፺፱ (ሉቃስ) ዓ/ም',
70 | $this->yetAnotherDateTime->format(Constants::DATE_GEEZ_ORTHODOX)
71 | );
72 | }
73 |
74 | public function test_date_connector()
75 | {
76 | foreach (Constants::FORMAT_MAPPER as $format => $function) {
77 | $this->assertEquals($this->dateTime->{$function}(), $this->dateTime->format($format));
78 | }
79 | }
80 |
81 | public function test_processor_trait()
82 | {
83 | $this->yetAnotherDateTime->add(new \DateInterval('P1D'));
84 | $this->assertEquals(
85 | 'ረቡዕ, 01-መስ-2000 23:00:00 የፓስፊክ ሰዓት አቆጣጠር (ሎስ አንጀለስ)',
86 | $this->yetAnotherDateTime->format(DATE_COOKIE)
87 | );
88 |
89 | $this->yetAnotherDateTime->sub(new \DateInterval('P3D'));
90 | $this->assertEquals(
91 | 'እሑ, 04 ጳጉ 1999 23:00:00 -0700',
92 | $this->yetAnotherDateTime->format(DATE_RFC2822)
93 | );
94 |
95 | $this->yetAnotherDateTime->modify('+1 hour');
96 | $this->assertEquals(
97 | 'ሰኞ, 05-ጳጉ-1999 00:00:00 የፓስፊክ ሰዓት አቆጣጠር (ሎስ አንጀለስ)',
98 | $this->yetAnotherDateTime->format(DATE_COOKIE)
99 | );
100 |
101 | $this->yetAnotherDateTime->setDate(2005, 5, 5);
102 |
103 | $this->assertEquals(
104 | '20050505',
105 | $this->yetAnotherDateTime->format('Ymd')
106 | );
107 |
108 | $this->yetAnotherDateTime->setTimestamp(1494567149);
109 | $this->assertEquals(
110 | 'ሐሙስ, 03-ግን-2009 22:32:29 የፓስፊክ ሰዓት አቆጣጠር (ሎስ አንጀለስ)',
111 | $this->yetAnotherDateTime->format(DATE_COOKIE)
112 | );
113 |
114 | $this->yetAnotherDateTime->setTime(6, 0, 0);
115 | $this->assertEquals(
116 | 'ሐሙስ 3th of ግንቦት 2009 06:00:00 ጡዋት',
117 | $this->yetAnotherDateTime->format('l j\t\h \o\f F Y h:i:s A')
118 | );
119 |
120 | $this->yetAnotherDateTime->setTimezone(new \DateTimeZone('America/Detroit'));
121 | $this->assertEquals(
122 | 'ሐሙስ the 3ኛው, ምስራቃዊ ሰዓት አቆጣጠር (ዲትሮይት)',
123 | $this->yetAnotherDateTime->format('l \t\h\e jS, T')
124 | );
125 | }
126 |
127 | public function test_datetime_diff()
128 | {
129 | $diff = $this->dateTime->diff($this->otherDateTime);
130 |
131 | $this->assertDiff($diff);
132 |
133 | $diff = $this->dateTime->diff($this->otherDateTime->toGregorian());
134 |
135 | $this->assertDiff($diff);
136 | }
137 |
138 | /**
139 | * @param $diff
140 | */
141 | protected function assertDiff($diff)
142 | {
143 | $this->assertEquals(2, $diff->y);
144 | $this->assertEquals(0, $diff->m);
145 | $this->assertEquals(4, $diff->d);
146 |
147 | $this->assertEquals(6, $diff->h);
148 | $this->assertEquals(8, $diff->i);
149 | $this->assertEquals(0, $diff->s);
150 |
151 | $this->assertEquals(734, $diff->days);
152 | }
153 |
154 | public function test_serialize()
155 | {
156 | $serialized = serialize($this->dateTime);
157 |
158 | /** @var DateTime $unserialized */
159 | $unserialized = unserialize($serialized);
160 |
161 | $diff = $unserialized->diff($this->otherDateTime);
162 |
163 | $this->assertDiff($diff);
164 |
165 | $this->assertEquals(
166 | 'ማክሰኞ፣ ኅዳር 21 ቀን 00:00:00 እኩለ፡ሌሊት የምስራቅ አፍሪካ ሰዓት (አዲስ አበባ) 1986 ዓ/ም',
167 | $this->dateTime->format(Constants::DATE_ETHIOPIAN)
168 | );
169 | }
170 |
171 | public function test_datetime_processor_chaining()
172 | {
173 | $this->expectWarning();
174 | $this->expectExceptionMessage('DateTime::modify(): Failed to parse time string (lorem ipsum) at position 0 (l): The timezone could not be found in the database');
175 |
176 | $this->assertFalse($this->dateTime->modify('lorem ipsum'));
177 | }
178 |
179 | public function test_gregorian_time()
180 | {
181 | $dates = [
182 | new DateTime(),
183 | DateTimeFactory::now(),
184 | DateTimeFactory::fromDateTime(new \DateTime('yesterday')),
185 | DateTimeFactory::fromTimestamp(1494567149),
186 | DateTimeFactory::fromConverter(new ToJdnConverter(20, 9, 1983)),
187 | ];
188 |
189 | foreach ($dates as $date) {
190 | $ethiopian = $date;
191 | $gregorian = $ethiopian->toGregorian();
192 |
193 | $this->assertEquals($ethiopian->getHour(), (int) $gregorian->format('H'));
194 | $this->assertEquals($ethiopian->getMinute(), (int) $gregorian->format('i'));
195 | $this->assertEquals($ethiopian->getSecond(), (int) $gregorian->format('s'));
196 | $this->assertEquals($ethiopian->getMicro(), (int) $gregorian->format('u'));
197 | }
198 | }
199 |
200 | public function test_year_name()
201 | {
202 | $this->assertEquals('ዮሐንስ', DateTimeFactory::of(2008, 1, 1)->format('X'));
203 | $this->assertEquals('ማቴዎስ', DateTimeFactory::of(2009, 1, 1)->format('X'));
204 | $this->assertEquals('ማርቆስ', DateTimeFactory::of(2010, 1, 1)->format('X'));
205 |
206 | $this->assertEquals('ሉቃስ', DateTimeFactory::of(2011, 13, 6)->format('X'));
207 |
208 | $this->assertEquals('ዮሐንስ', DateTimeFactory::of(2012, 1, 1)->format('X'));
209 | $this->assertEquals('ማቴዎስ', DateTimeFactory::of(2013, 1, 1)->format('X'));
210 | }
211 | }
212 |
--------------------------------------------------------------------------------
/src/Operations/Formatter.php:
--------------------------------------------------------------------------------
1 | getValueOfFormatCharacter($format_char, $skip_next);
36 | }
37 |
38 | // remove null bits if they exist
39 | return str_replace("\0", '', $result);
40 | }
41 |
42 | /**
43 | * Return the value of the format character.
44 | *
45 | * @param string $name of the field
46 | * @param bool $skip
47 | *
48 | * @return string
49 | */
50 | protected function getValueOfFormatCharacter(string $name, bool &$skip = false): string
51 | {
52 | if (($r = $this->shouldWeSkip($name, $skip)) !== false) {
53 | return ''.$r;
54 | }
55 |
56 | if ($this->isOverrideFormatCharacter($name)) {
57 | return ''.$this->{Constants::FORMAT_MAPPER[$name]}();
58 | }
59 |
60 | return $this->dateTime->format($name);
61 | }
62 |
63 | /**
64 | * (01-30) Day of the month, 2 digits with leading zeros.
65 | *
66 | * @return string
67 | */
68 | public function getDayTwoDigit(): string
69 | {
70 | $day = $this->getValueOfFormatCharacter('j');
71 |
72 | return strlen($day) === 1 ? "0$day" : $day;
73 | }
74 |
75 | /**
76 | * (ሰኞ-እሑድ) A full textual representation of the day of the week.
77 | *
78 | * return string
79 | */
80 | public function getTextualDay(): string
81 | {
82 | return Constants::WEEK_NAME[$this->getDayOfWeek()];
83 | }
84 |
85 | /**
86 | * (ሰኞ-እሑ) A textual representation of a day, two letters.
87 | *
88 | * return string
89 | */
90 | public function getTextualDayShort(): string
91 | {
92 | $week = $this->getValueOfFormatCharacter('l');
93 |
94 | return mb_substr($week, 0, 2, 'UTF-8');
95 | }
96 |
97 | /**
98 | * (መስከረም-ጳጉሜን) A full textual representation of a month.
99 | *
100 | * @return string
101 | */
102 | public function getTextualMonth(): string
103 | {
104 | return Constants::MONTHS_NAME[$this->getMonth()];
105 | }
106 |
107 | /**
108 | * (መስ - ጳጉ) A short textual representation of a month, two letters.
109 | *
110 | * @return string
111 | */
112 | public function getTextualMonthShort(): string
113 | {
114 | $F = $this->getValueOfFormatCharacter('F');
115 |
116 | return mb_substr($F, 0, 2, 'UTF-8');
117 | }
118 |
119 | /**
120 | * (01-13) Numeric representation of a month, with leading zeros.
121 | *
122 | * @return string
123 | */
124 | public function getMonthTwoDigit(): string
125 | {
126 | $n = $this->getValueOfFormatCharacter('n');
127 |
128 | return (strlen($n) === 1) ? "0$n" : "$n";
129 | }
130 |
131 | /**
132 | * (1 or 0) Whether it's a leap year.
133 | *
134 | * @return string
135 | */
136 | public function getLeapYearString(): string
137 | {
138 | return $this->isLeapYear() ? '1' : '0';
139 | }
140 |
141 | /**
142 | * returns 97 for the year 1997.
143 | *
144 | * @return string
145 | */
146 | public function getYearShort(): string
147 | {
148 | $Y = $this->getValueOfFormatCharacter('Y');
149 |
150 | return mb_substr($Y, strlen($Y) - 2, 2);
151 | }
152 |
153 | /**
154 | * Return the amharic equivalent of AM & PM.
155 | *
156 | * (እኩለ፡ሌሊት-ምሽት)
157 | *
158 | * It suppose to format 'Ante meridiem' and 'Post meridiem'
159 | * But we Ethiopians classify the day in ten parts
160 | * and we don't have Uppercase and Lowercase letters
161 | *
162 | * @link http://web.archive.org/web/20140331152859/http://ethiopic.org/Calendars/
163 | *
164 | * @return string
165 | */
166 | public function getTimeOfDay(): string
167 | {
168 | $array = [
169 | 'እኩለ፡ሌሊት' => [23, 0],
170 | 'ውደቀት' => [1, 2, 3],
171 | 'ንጋት' => [4, 5],
172 | 'ጡዋት' => [6, 7, 8],
173 | 'ረፋድ' => [9, 10, 11],
174 | 'እኩለ፡ቀን' => [12],
175 | 'ከሰዓት፡በኋላ' => [13, 14, 15],
176 | 'ወደማታ' => [16, 17],
177 | 'ሲደነግዝ' => [18, 19],
178 | 'ምሽት' => [20, 21, 22],
179 | ];
180 |
181 | $hour = $this->getHour();
182 |
183 | $result = array_filter($array, function ($value) use ($hour) {
184 | return in_array($hour, $value, true);
185 | });
186 |
187 | return key($result);
188 | }
189 |
190 | /**
191 | * 1 (for 'ልደታ'), 2 (for አባ፡ጉባ), ... 30 (for ማርቆስ).
192 | *
193 | * @return string the ethiopian orthodox day name
194 | */
195 | public function getOrthodoxDay(): string
196 | {
197 | return Constants::ORTHODOX_DAY_NAME[$this->getDay()];
198 | }
199 |
200 | /**
201 | * ዓ/ም or ዓ/ዓ.
202 | *
203 | * @return string
204 | */
205 | public function getTextualEra(): string
206 | {
207 | return $this->getYear() > 0 ? 'ዓ/ም' : 'ዓ/ዓ';
208 | }
209 |
210 | /**
211 | * ማቴዎስ, ማርቆስ, ሉቃስ or ዮሐንስ.
212 | *
213 | * @return string the ethiopian orthodox year name
214 | */
215 | public function getOrthodoxYear(): string
216 | {
217 | return Constants::ORTHODOX_YEAR_NAME[$this->getYear() % 4];
218 | }
219 |
220 | /**
221 | * Return the year in geez number.
222 | *
223 | * @throws \Geezify\Exception\NotAnIntegerArgumentException
224 | *
225 | * @return string
226 | */
227 | public function getYearInGeez(): string
228 | {
229 | return Geezify::create()->toGeez($this->getYear());
230 | }
231 |
232 | /**
233 | * Return the day in geez number.
234 | *
235 | * @return string
236 | */
237 | public function getDayInGeez(): string
238 | {
239 | return Geezify::create()->toGeez($this->getDay());
240 | }
241 |
242 | /**
243 | * Return an empty string.
244 | *
245 | * @return string
246 | */
247 | public function getTimeZoneString(): string
248 | {
249 | $name = $this->getTimezone()->getName();
250 |
251 | return Constants::TIME_ZONES[$name] ?? sprintf('ጂ ኤም ቲ%s', $name);
252 | }
253 |
254 | /**
255 | * Return `ኛው` rather than st,nd,rd, and th.
256 | *
257 | * @return string
258 | */
259 | public function getOrdinalSuffix(): string
260 | {
261 | return 'ኛው';
262 | }
263 |
264 | /**
265 | * RFC 2822 formatted date.
266 | *
267 | * @return string
268 | */
269 | public function getFormattedDate(): string
270 | {
271 | return $this->format(DATE_RFC2822);
272 | }
273 |
274 | /**
275 | * @param string $name
276 | *
277 | * @return bool
278 | */
279 | protected function isOverrideFormatCharacter($name): bool
280 | {
281 | return array_key_exists($name, Constants::FORMAT_MAPPER);
282 | }
283 |
284 | /**
285 | * @param string $name
286 | * @param bool $skip
287 | *
288 | * @return string|false
289 | */
290 | protected function shouldWeSkip($name, &$skip)
291 | {
292 | if ($this->shouldWeSkip4Real($name, $skip)) {
293 | return $this->skipCharacter($name, $skip);
294 | }
295 |
296 | return false;
297 | }
298 |
299 | /**
300 | * @param $name
301 | * @param $skip
302 | *
303 | * @return bool
304 | */
305 | protected function shouldWeSkip4Real($name, &$skip): bool
306 | {
307 | return $this->isSkipCharacter($name) || $skip;
308 | }
309 |
310 | /**
311 | * @param $name
312 | * @param $skip
313 | *
314 | * @return string
315 | */
316 | protected function skipCharacter($name, &$skip): string
317 | {
318 | if ($skip) {
319 | $skip = false;
320 |
321 | return $name;
322 | }
323 |
324 | if ($this->isSkipCharacter($name)) {
325 | $skip = true;
326 | }
327 |
328 | return '';
329 | }
330 |
331 | /**
332 | * @param $name
333 | *
334 | * @return bool
335 | */
336 | protected function isSkipCharacter($name): bool
337 | {
338 | return $name === '\\';
339 | }
340 | }
341 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Andegna Calender 
2 |
3 | 
4 | [](https://styleci.io/repos/30183050)
5 | [](https://scrutinizer-ci.com/g/andegna/calender/?branch=master)
6 | [](https://scrutinizer-ci.com/g/andegna/calender/?branch=master)
7 | [](https://packagist.org/packages/andegna/calender)
8 | [](https://packagist.org/packages/andegna/calender)
9 | [](https://packagist.org/packages/andegna/calender)
10 | [](https://packagist.org/packages/andegna/calender)
11 | [](https://app.fossa.io/projects/git%2Bgithub.com%2Fandegna%2Fcalender?ref=badge_shield)
12 |
13 | [](https://insight.symfony.com/projects/22a1a0d1-9999-4771-90eb-a79271985256)
14 |
15 | > If you ever want to convert **Ethiopian Calender** to any other calendar system
16 | > (like the Gregorian Calendar) this is the right (well-tested, well designed, high quality) package for you.
17 | >
18 | > And by the way it also supports Amharic date formatting and much much more.
19 |
20 |
21 |
22 | - [Basic Usage](#basic-usage-hammer)
23 | - [Requirement](#requirement)
24 | - [Installation](#installation)
25 | - [Conversion](#conversion)
26 | - [From Ethiopian Date](#from-Ethiopian-Date)
27 | - [From Timestamp](#from-timestamp)
28 | - [From DateTime object](#from-dateTime-object)
29 | - [From date string](#from-date-string)
30 | - [From the system time](#from-the-system-time)
31 | - [To DateTime](#to-datetime)
32 | - [Low level Conversion](#low-level-conversion)
33 | - [How PHP calendar conversion works](#how-php-calendar-conversion-works)
34 | - [From JDN](#from-jdn)
35 | - [To JDN](#to-jdn)
36 | - [Practical Example](#practical-example)
37 | - [Manipulation](#manipulation)
38 | - [Warning](#warning)
39 | - [Manipulating the internal date time](#manipulating-the-internal-date-time)
40 | - [Formatting](#formatting)
41 | - [Introduction](#introduction)
42 | - [Additional character formats](#additional-character-formats)
43 | - [Constants](#constants)
44 | - [Holidays](#holidays)
45 | - [Easter](#easter)
46 | - [Validators](#validators)
47 | - [Contributing](#contributing)
48 |
49 |
50 | ## Basic Usage :hammer: [↑](#top)
51 |
52 | Just to give you the 10,000-foot view (:airplane:) of the package.
53 |
54 | ```php
55 | // create a gregorian date using PHP's built-in DateTime class
56 | $gregorian = new DateTime('next monday');
57 |
58 | // just pass it to Andegna\DateTime constractor and you will get $ethiopian date
59 | $ethipic = new Andegna\DateTime($gregorian);
60 | ```
61 |
62 | Format it
63 |
64 | ```php
65 | // format it
66 | // ሰኞ፣ ግንቦት ፯ ቀን (ሥላሴ) 00:00:00 እኩለ፡ሌሊት EAT ፳፻፱ (ማርቆስ) ዓ/ም
67 | echo $ethipic->format(Andegna\Constants::DATE_GEEZ_ORTHODOX);
68 |
69 | // ሰኞ፣ ግንቦት 07 ቀን 00:00:00 እኩለ፡ሌሊት EAT 2009 ዓ/ም
70 | echo $ethipic->format(Andegna\Constants::DATE_ETHIOPIAN);
71 | ```
72 |
73 | Modify it
74 |
75 | ```php
76 | $ethipic->modify('+8 hours');
77 | $ethipic->sub(new DateInterval('PT30M')); // 30 minutes
78 |
79 | // ሰኞ, 07-ግን-2009 07:30:00 EAT
80 | echo $ethipic->format(DATE_COOKIE);
81 | ```
82 |
83 | Get what you want :wink:
84 |
85 | ```php
86 | echo $ethipic->getYear(); // 2009
87 | echo $ethipic->getMonth(); // 9
88 | echo $ethipic->getDay(); // 7
89 |
90 | echo $ethipic->getTimestamp(); // 1494822600
91 |
92 | // turn it back to gregorian
93 | // Monday, 15-May-2017 07:30:00 EAT
94 | echo $ethipic->toGregorian()->format(DATE_COOKIE);
95 | ```
96 |
97 |
98 | ## Requirement [↑](#top)
99 |
100 | Andegna Calender requires `php: >=7.0` with fire and blood :fire: :dragon:.
101 |
102 | Please notice the name of this package is `andegna/calender` not `andegna/calendar`.
103 | It's a spelling mistake am not intending to fix.
104 |
105 |
106 | ## Installation [↑](#top)
107 |
108 | **Andegna Calender** utilizes [Composer](https://getcomposer.org/) to manage its dependencies.
109 | So, before using this, make sure you have Composer installed on your machine.
110 |
111 | > Composer is a tool for dependency management in PHP. It allows you to declare the libraries your project depends on and it will manage (install/update) them for you.
112 |
113 | If you never used composer before :flushed:, PLEASE read some [intro here](https://getcomposer.org/doc/00-intro.md) before you write any PHP code again.
114 |
115 | ```bash
116 | composer require andegna/calender
117 | ```
118 |
119 |
120 | ## Conversion [↑](#top)
121 |
122 | Before we talk about calendar conversion, we better know how the `Andegna\DateTime` class works internally.
123 |
124 | The `Andegna\DateTime` class is just a wrapper around PHP's built-in [`DateTime`](http://uk1.php.net/manual/en/class.datetime.php)
125 | object and implements the PHP [`DateTimeInterface`](http://uk1.php.net/manual/en/class.datetimeinterface.php)
126 | (OK! I lied on one part but trust me you don't wanna know that :smile:).
127 |
128 | So `Andegna\DateTime` keep hold of the gregorian date and overrides the `format`, `getTimestamp`, `add`, 'diff' and such methods to give you an Ethiopian Calendar equivalent.
129 |
130 | That's how it basically works.
131 |
132 |
133 | ### From Ethiopian Date [↑](#top)
134 |
135 | You can create an `Andegna\DateTime` from a given Ethiopia Date.
136 |
137 | Let's "create"
138 |
139 | ```php
140 | $millennium = Andegna\DateTimeFactory::of(2000, 1, 1);
141 |
142 | // ረቡዕ፣ መስከረም 01 ቀን (ልደታ) 00:00:00 እኩለ፡ሌሊት EAT 2000 (ማቴዎስ) ዓ/ም
143 | echo $millennium->format(\Andegna\Constants::DATE_ETHIOPIAN_ORTHODOX).PHP_EOL;
144 |
145 | // Wednesday, 12-Sep-2007 00:00:00 EAT
146 | echo $millennium->toGregorian()->format(DATE_COOKIE).PHP_EOL;
147 |
148 | $fall_of_derg = Andegna\DateTimeFactory::of(1983, 9, 20, 7, 43, 21, new DateTimeZone('Africa/Addis_Ababa'));
149 |
150 | // ማክሰኞ፣ ግንቦት 20 ቀን (ሕንፅተ) 07:43:21 ጡዋት EAT 1983 (ዮሐንስ) ዓ/ም
151 | echo $fall_of_derg->format(\Andegna\Constants::DATE_ETHIOPIAN_ORTHODOX).PHP_EOL;
152 |
153 | // Tuesday, 28-May-1991 07:43:21 EAT
154 | echo $fall_of_derg->toGregorian()->format(DATE_COOKIE).PHP_EOL;
155 | ```
156 |
157 |
158 | ### From Timestamp [↑](#top)
159 |
160 | Let's assume you have a timestamp from same were probably `time()` function or from some kind of database.
161 |
162 | You can get `Andegna\DateTime` object like this
163 | ```php
164 | $timestamp = time(); // or some other place ¯\_(ツ)_/¯
165 |
166 | $ethipic = Andegna\DateTimeFactory::fromTimestamp($timestamp);
167 | ```
168 |
169 | And you are done. You can also or pass a `DateTimeZone` object if you want too
170 |
171 | ```php
172 | $sheger = new DateTimeZone('Africa/Addis_Ababa');
173 |
174 | $ethiopic = Andegna\DateTimeFactory::fromTimestamp($timestamp, $sheger);
175 | ```
176 |
177 |
178 | ### From DateTime object [↑](#top)
179 |
180 | If you already have a `DateTime` object, just give it to me :smile:
181 |
182 | ```php
183 | $gregorian = new DateTime('Thu, 11 May 2017 19:01:26 GMT');
184 | $ethiopic = Andegna\DateTimeFactory::fromDateTime($gregorian);
185 |
186 | // or just pass it through the constractor
187 | $ethiopic = new Andegna\DateTime(new DateTime('next sunday'));
188 | ```
189 |
190 |
191 | ### From date string [↑](#top)
192 |
193 | This is not actually part of this package but someone probably having a hard time.
194 |
195 | It generally boils down to two options. Do you know the format of the date string or not.
196 |
197 | If you know the format of the date (you probably should) you can create a gregorian `DateTime`
198 | like this
199 |
200 | ```php
201 | // passing the format followed by the date string you got
202 | $gregorian1 = DateTime::createFromFormat('j-M-Y', '15-Feb-2009');
203 | $gregorian2 = DateTime::createFromFormat('m-j-Y', '12-31-1999');
204 | $gregorian3 = DateTime::createFromFormat('Y-m-d H:i:s', '2009-02-15 15:16:17');
205 | ```
206 |
207 | To figure out the format please check [this link](http://php.net/manual/en/datetime.createfromformat.php) or search for "PHP date function".
208 |
209 | But if don't know the format is or don't care to figure it out just try to pass it to the DateTime constructor. It will "probably" figure out the format of the date string
210 |
211 | ```php
212 | $gregorian1 = new DateTime('next sunday');
213 | $gregorian2 = new DateTime('yesterday');
214 | $gregorian3 = new DateTime('1999-12-31');
215 | $gregorian4 = new DateTime('2123-12-31 12:34:56');
216 |
217 | $gregorian_bad = new DateTime('12-31-1999'); // this one probably fails
218 | ```
219 |
220 |
221 | ### From the system time [↑](#top)
222 |
223 | You obviously can do this
224 | ```php
225 | $gregorian = new DateTime('now');
226 | $ethiopic = Andegna\DateTimeFactory::fromDateTime($gregorian);
227 |
228 | // but we provided some shortcuts
229 | $now1 = \Andegna\DateTimeFactory::now();
230 | $now2 = new DateTime();
231 |
232 | // if you wanna specify time zone
233 | $sheger = new DateTimeZone('Africa/Addis_Ababa');
234 | $now3 = \Andegna\DateTimeFactory::now($sheger);
235 | ```
236 |
237 |
238 | ### To DateTime [↑](#top)
239 |
240 | If you want the internal `DateTime` object (A.K.A convert to gregorian calendar).
241 |
242 | ```php
243 | // create some Ethiopian date how ever you want
244 | $ethiopian_date = \Andegna\DateTimeFactory::now();
245 |
246 | // you get a PHP DateTime object to play with
247 | $gregorian = $now->toGregorian();
248 | ```
249 | > Warning: the returned DateTime object is just a clone. So changes/modification to the returned object will not affect the Ethiopic date.
250 |
251 |
252 | ## Low level Conversion [↑](#top)
253 |
254 | If you are a geek like me, you are probably interested in Calendar coz it has Astronomy, Maths, and History.
255 |
256 |
257 | ### How PHP calendar conversion works [↑](#top)
258 |
259 | > The calendar extension presents a series of functions to simplify converting between different calendar formats (except Ethiopian).
260 | > The intermediary or standard it is based on is the **Julian Day Count**. The Julian Day Count is a count of days starting from January 1st, 4713 B.C.
261 | > To convert between calendar systems, you must first convert to Julian Day Count, then to the calendar system of your choice.
262 | > Julian Day Count is very different from the Julian Calendar! For more information on Julian Day Count, visit » [http://www.hermetic.ch/cal_stud/jdn.htm](http://www.hermetic.ch/cal_stud/jdn.htm).
263 | > For more information on calendar systems visit » [http://www.fourmilab.ch/documents/calendar/](http://www.fourmilab.ch/documents/calendar/). Excerpts from this page are included in these instructions and are in quotes.
264 |
265 | Those words are straight from the [php docs](http://php.net/manual/en/intro.calendar.php).
266 |
267 | So we need to implement two things to convert Ethiopian date to any other calendar.
268 | 1. Convert Ethiopian Date To Julian Date Count
269 | 2. Convert Julian Date Count To Ethiopian Date
270 |
271 | If you wanna know the algorithms check out the only reliable resource at [this link](http://web.archive.org/web/20140331152859/http://ethiopic.org/Calendars/).
272 |
273 | or check out my gist on GitHub at [this link](https://gist.github.com/SamAsEnd/70f2587c002070d2a1985f0741111554)
274 |
275 |
276 | ### From JDN [↑](#top)
277 |
278 | ```php
279 | use Andegna\Converter\FromJdnConverter;
280 |
281 | $jdn = 2457886;
282 | $converter = new FromJdnConverter($jdn);
283 |
284 | $day = $converter->getDay(); // 4
285 | $month = $converter->getMonth(); // 9
286 | $year = $converter->getYear(); // 2009
287 | ```
288 |
289 |
290 | ### To JDN [↑](#top)
291 |
292 | ```php
293 | use Andegna\Converter\ToJdnConverter;
294 |
295 | $converter = new ToJdnConverter(21,3,1986);
296 | echo $jdn = $converter->getJdn(); // 2449322
297 | ```
298 |
299 |
300 | ### Practical Example [↑](#top)
301 |
302 | Now with those handy tools in our hand, we can convert Ethiopian date to any other date.
303 |
304 | Let's convert to Jewish for example
305 |
306 | ```php
307 | $et = new Andegna\DateTime();
308 |
309 | // ዓርብ, 04-ግን-2009 14:41:00 EAT
310 | echo $et->format(DATE_COOKIE);
311 |
312 | // create a Ethiopian Date `ToJdnConverter`
313 | $converter = new Andegna\Converter\ToJdnConverter($et->getDay(), $et->getMonth(), $et->getYear());
314 |
315 | // convert it to jdn
316 | $jdn = $converter->getJdn();
317 |
318 | // use the built-in php function to convert the jdn to the jewish calendar
319 | $jewish_date1 = jdtojewish($jdn);
320 |
321 | // 9/16/5777
322 | echo $jewish_date1;
323 |
324 | // it also support formating for the return string
325 | $jewish_date2 = jdtojewish($jdn, true, CAL_JEWISH_ADD_ALAFIM_GERESH);
326 |
327 | // convert the return string to utf-8
328 | $jewish_date2 = iconv ('WINDOWS-1255', 'UTF-8', $jewish_date2);
329 |
330 | // טז אייר ה'תשעז
331 | echo $jewish_date2;
332 | ```
333 |
334 | Let's convert Julian Calendar to Ethiopian Calendar as a second example
335 |
336 | ```php
337 | $day = 29;
338 | $month = 4;
339 | $year = 2017;
340 |
341 | // get the jdn using the built in php function
342 | $jdn = juliantojd($month, $day, $year);
343 |
344 | // convert the jd to Ethiopian Date
345 | $converter = new Andegna\Converter\FromJdnConverter($jdn);
346 |
347 | // create a `Andegna\DateTime` from the converted date
348 | $ethiopic = Andegna\DateTimeFactory::fromConverter($converter);
349 |
350 | // ዓርብ, 04-ግን-2009 00:00:00 EAT
351 | echo $ethiopic->format(DATE_COOKIE);
352 |
353 | // Friday, 12-May-2017 00:00:00 EAT
354 | echo $ethiopic->toGregorian()->format(DATE_COOKIE);
355 | ```
356 |
357 | #### List of supported calendars built into PHP
358 | - French Republican Calendar
359 | - Gregorian Calendar
360 | - Jewish calendar
361 | - Julian Calendar
362 | - Unix (I know what you are thinking. It's not a calendar but it handy)
363 |
364 | Click [here](http://php.net/manual/en/ref.calendar.php) to read more about those calendar function
365 |
366 |
367 | ## Manipulation [↑](#top)
368 |
369 |
370 | ### Warning [↑](#top)
371 |
372 | > The DateTime processor works on the internal gregorian `DateTime`. And manipulating months and years probably give an expected results.
373 |
374 |
375 | ### Manipulating the internal date time [↑](#top)
376 |
377 | You probably need to read about [DateTimeInterval](http://php.net/manual/en/class.dateinterval.php) if you don't already know.
378 |
379 | To give you a short summary, `DateInterval` implements the [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601#Durations) durations.
380 |
381 | Durations are a component of time intervals and define the amount of intervening time in a time interval.
382 | Durations are represented by the format **`P[n]Y[n]M[n]DT[n]H[n]M[n]S`** or **`P[n]W`**.
383 |
384 | In these representations, the [n] is replaced by the value for each of the date and time elements that follow the [n].
385 |
386 | Leading zeros are not required. The capital letters P, Y, M, W, D, T, H, M, and S are designators for each of the date and time elements and are not replaced.
387 |
388 | - **P** is the duration designator (for the period) placed at the start of the duration representation.
389 | - **Y** is the year designator that follows the value for the number of years.
390 | - **M** is the month designator that follows the value for the number of months.
391 | - **W** is the week designator that follows the value for the number of weeks.
392 | - **D** is the day designator that follows the value for the number of days.
393 | - **T** is the time designator that precedes the time components of the representation.
394 | - **H** is the hour designator that follows the value for the number of hours.
395 | - **M** is the minute designator that follows the value for the number of minutes.
396 | - **S** is the second designator that follows the value for the number of seconds.
397 |
398 | > For example, **"P3Y6M4DT12H30M5S"** represents a duration of "three years, six months, four days, twelve hours, thirty minutes, and five seconds".
399 |
400 | ```php
401 | // let's start from today
402 | $today = new Andegna\DateTime();
403 |
404 | // Adds an amount of days, months, years, hours, minutes and seconds to a DateTime object
405 | $tomorrow = $today->add(new DateInterval('P1D'));
406 | $after_some_days = $today->add(new DateInterval('P10DT4H'));
407 | $after_6_hours = $today->add(new DateInterval('PT6H'));
408 |
409 | // Subtracts an amount of days, months, years, hours, minutes and seconds from a DateTime object
410 | $yesterday = $today->sub(new DateInterval('P1D'));
411 | $before_some_days = $today->sub(new DateInterval('P10DT4H'));
412 | $before_6_hours = $today->sub(new DateInterval('PT6H'));
413 |
414 | // Alters the DateTime object
415 | $tomorrow = $today->modify('+1 day');
416 | $yesterday = $today->modify('-1 day');
417 | $after_30_minutes = $today->modify('+30 minutes');
418 | $after_30_minutes = $today->modify('next sunday');
419 | ```
420 |
421 | If you want to get the difference between dates
422 |
423 | ```php
424 | $today = new Andegna\DateTime();
425 | $tomorrow = (new Andegna\DateTime())->add(new DateInterval('P1DT2M3S'));
426 |
427 | $diff = $today->diff($tomorrow); // returns a DateTimeInterval
428 | var_dump($diff);
429 | ```
430 |
431 | will output something like this
432 | ```
433 | object(DateInterval)[9]
434 | ...
435 | public 'd' => int 1
436 | public 'h' => int 0
437 | public 'i' => int 2
438 | public 's' => int 3
439 | ...
440 | ```
441 |
442 | ## Formatting [↑](#top)
443 |
444 |
445 | ### Introduction [↑](#top)
446 |
447 | PHP built-in `DateTime` class has a `format` method used to format dates.
448 |
449 | > Read about the format method [here](http://uk1.php.net/manual/en/datetime.format.php)
450 | >
451 | > Read out the format characters [here](http://uk1.php.net/manual/en/function.date.php)
452 |
453 | If you read or already know how PHP date function works, you already know how exactly the formatting works.
454 |
455 | ```php
456 | $now = new Andegna\DateTime();
457 |
458 | // Let's play a game. It's called "Spot the difference"
459 | echo $now->format(DATE_COOKIE); // ዓርብ, 04-ግን-2009 02:09:52 EAT
460 | echo $now->toGregorian()->format(DATE_COOKIE); // Friday, 12-May-2017 02:09:52 EAT
461 |
462 | echo $now->format(DATE_ATOM); // 2009-09-04EAT02:09:52+03:00
463 | echo $now->toGregorian()->format(DATE_ATOM); // 2017-05-12T02:09:52+03:00
464 |
465 | echo $now->format('F j ቀን Y'); // ግንቦት 4 ቀን 2009
466 | echo $now->toGregorian()->format('F j ቀን Y'); // May 12 ቀን 2017
467 |
468 | echo $now->format('H:i:s A'); // 10:09:17 ረፋድ
469 | echo $now->toGregorian()->format('H:i:s A'); // 10:09:17 AM
470 | ```
471 |
472 | ### Additional character formats [↑](#top)
473 |
474 | | Format Character | Description | Example |
475 | | ---------------- | ------------- | ------- |
476 | | x | Orthodox day name | 1 => ልደታ, 12 => ሚካኤል |
477 | | X | Orthodox year name | ማቴዎስ, ማርቆስ, ሉቃስ or ዮሐንስ |
478 | | E | Era in Amharic | ዓ/ዓ or ዓ/ም |
479 | | K | Year in geez numeber | ፳፻፱ |
480 | | V | Day in geez numebr | ፪ |
481 |
482 |
483 | ### Constants [↑](#top)
484 |
485 | We have already defined some handy constants to print as it's custom in Ethiopia :heart: .
486 |
487 | ```php
488 | $date = new Andegna\DateTime();
489 |
490 | // ዓርብ፣ ግንቦት 04 ቀን 02:35:45 ውደቀት EAT 2009 ዓ/ም
491 | echo $date->format(Andegna\Constants::DATE_ETHIOPIAN);
492 |
493 | $date->modify('+8 hours');
494 |
495 | // ዓርብ፣ ግንቦት 04 ቀን (ዮሐንስ) 10:35:45 ረፋድ EAT 2009 (ማርቆስ) ዓ/ም
496 | echo $date->format(Andegna\Constants::DATE_ETHIOPIAN_ORTHODOX);
497 |
498 | $date->modify('+1 year');
499 |
500 | // ቅዳሜ፣ ግንቦት ፬ ቀን 10:35:45 ረፋድ EAT ፳፻፲ ዓ/ም
501 | echo $date->format(Andegna\Constants::DATE_GEEZ);
502 |
503 | $date->modify('-3 years')->modify('+1 day');
504 |
505 | // ረቡዕ፣ ግንቦት ፭ ቀን (አቦ) 10:35:45 ረፋድ EAT ፳፻፯ (ዮሐንስ) ዓ/ም
506 | echo $date->format(Andegna\Constants::DATE_GEEZ_ORTHODOX);
507 | ```
508 |
509 | As you saw 3D, the constants all start with `DATE_` and followed by `ETHIOPIAN` or `GEEZ`.
510 |
511 | The one followed by `GEEZ` will return the day and the year in geez and the `ETHIOPIAN` with spit an ASCII numbers which we Ethiopian always use.
512 |
513 | Lastly, if you append `_ORTHODOX` you will get the orthodox day name and orthodox year name.
514 |
515 |
516 | ## Holidays [↑](#top)
517 |
518 |
519 | ### Easter [↑](#top)
520 |
521 | Calculating easter date feels like shooting a moving target. And everyone thinks calculating easter date is like impossible, some think like it's only possible if you are a deeply religious and some think it's decided by the church. But calculating easter date ( also called Computus) is not that much complex.
522 |
523 | In the simplest form, Easter is the first Sunday following the full moon that follows the northern spring (vernal) equinox.
524 |
525 | That sounds complex and was hard for the ages but not for the 21st century.
526 |
527 | If you are interested in HOW it's calculated, I will post it on my upcoming blog.
528 | You can read [this](https://en.wikipedia.org/wiki/Computus) in the meanwhile.
529 |
530 | Let's see how you can get the easter date for a given year
531 |
532 | ```php
533 | $easter = new Andegna\Holiday\Easter();
534 |
535 | // እሑድ፣ ሚያዝያ 08 ቀን 00:00:00 እኩለ፡ሌሊት EAT 2009 ዓ/ም
536 | echo $easter->get(2009)->format(Andegna\Constants::DATE_ETHIOPIAN).PHP_EOL;
537 |
538 | // or just ...
539 | foreach ([2006,2007,2008,2009,2010,2011,2012] as $year) {
540 | echo $easter->get($year)->format(Andegna\Constants::DATE_ETHIOPIAN).PHP_EOL;
541 | }
542 | ```
543 | will output
544 | ```
545 | እሑድ፣ ሚያዝያ 12 ቀን 00:00:00 እኩለ፡ሌሊት EAT 2006 ዓ/ም
546 | እሑድ፣ ሚያዝያ 04 ቀን 00:00:00 እኩለ፡ሌሊት EAT 2007 ዓ/ም
547 | እሑድ፣ ሚያዝያ 23 ቀን 00:00:00 እኩለ፡ሌሊት EAT 2008 ዓ/ም
548 | እሑድ፣ ሚያዝያ 08 ቀን 00:00:00 እኩለ፡ሌሊት EAT 2009 ዓ/ም
549 | እሑድ፣ መጋቢት 30 ቀን 00:00:00 እኩለ፡ሌሊት EAT 2010 ዓ/ም
550 | እሑድ፣ ሚያዝያ 20 ቀን 00:00:00 እኩለ፡ሌሊት EAT 2011 ዓ/ም
551 | እሑድ፣ ሚያዝያ 11 ቀን 00:00:00 እኩለ፡ሌሊት EAT 2012 ዓ/ም
552 | ```
553 |
554 |
555 | ## Validators [↑](#top)
556 |
557 | Validation. You probably need that too.
558 |
559 | To check if Ethiopia date (given `day`, `month` and `year`) is valid you need to do all this
560 |
561 | - Check if the `day` is between `1` and `30` inclusive
562 | - Check if the `month` is between `1` and `13` inclusive
563 | - If the `month` is `13` check if the `day` is between `1` and `6` inclusive
564 | - If the `month` is `13` and the `day` is `6` check if the year is a leap year
565 |
566 | or you can use our validator
567 |
568 | #### DateValidator
569 |
570 | ```php
571 | use Andegna\Validator\DateValidator;
572 |
573 | // true
574 | $is_valid1 = (new DateValidator(15,9, 2009))->isValid();
575 |
576 | // false
577 | $is_valid2 = (new DateValidator(6,13, 2009))->isValid();
578 | ```
579 |
580 | #### LeapYearValidator
581 |
582 | ```php
583 | use Andegna\Validator\LeapYearValidator;
584 |
585 | // false
586 | $is_valid3 = (new LeapYearValidator(2009))->isValid();
587 |
588 | // true
589 | $is_valid4 = (new LeapYearValidator(2007))->isValid();
590 | ```
591 |
592 |
593 | ## Contributing [↑](#top)
594 |
595 | Fork it
596 | Create your feature branch (git checkout -b my-new-feature)
597 | Commit your changes (git commit -am 'Add some feature')
598 | Push to the branch (git push origin my-new-feature)
599 | Create new Pull Request
600 |
601 |
602 | ## License
603 | [](https://app.fossa.io/projects/git%2Bgithub.com%2Fandegna%2Fcalender?ref=badge_large)
604 |
--------------------------------------------------------------------------------
/src/Constants.php:
--------------------------------------------------------------------------------
1 | 'መስከረም', 'ጥቅምት', 'ኅዳር', 'ታኅሣሥ', 'ጥር', 'የካቲት',
18 | 'መጋቢት', 'ሚያዝያ', 'ግንቦት', 'ሰኔ', 'ሐምሌ', 'ነሐሴ', 'ጳጉሜን', ];
19 |
20 | const WEEK_NAME = [1 => 'ሰኞ', 'ማክሰኞ', 'ረቡዕ', 'ሐሙስ', 'ዓርብ', 'ቅዳሜ', 'እሑድ'];
21 |
22 | const ORTHODOX_YEAR_NAME = ['ዮሐንስ', 'ማቴዎስ', 'ማርቆስ', 'ሉቃስ'];
23 |
24 | const ORTHODOX_DAY_NAME = [
25 | 1 => 'ልደታ', 'አባ፡ጉባ', 'በእታ', 'ዮሐንስ', 'አቦ',
26 | 'ኢያሱስ', 'ሥላሴ', 'አባ፡ኪሮስ', 'ቶማስ', 'መስቀል',
27 | 'ሐና፡ማርያም', 'ሚካኤል', 'እግዚሐር፡አብ', 'አቡነ፡አረጋዊ',
28 | 'ቂርቆስ', 'ኪዳነ፡ምሕረት', 'እስጢፋኖስ', 'ተክለ፡አልፋ',
29 | 'ገብርኤል', 'ሕንፅተ', 'ማርያም', 'ኡራኤል', 'ጊዮርጊስ',
30 | 'ተክለ፡ሐይማኖት', 'መርቆርዮስ', 'ዮሴፍ', 'መድኀኔ፡ዓለም',
31 | 'አማኑኤል', 'ባለ፡እግዚአብሔር', 'ማርቆስ',
32 | ];
33 |
34 | const FORMAT_MAPPER = [
35 | 'j' => 'getDay', // 1 - 30
36 | 'd' => 'getDayTwoDigit', // 01 - 30
37 | 'l' => 'getTextualDay', // ሰኞ - እሑድ
38 | 'D' => 'getTextualDayShort', // ሰኞ - እሑ
39 | 'w' => 'getDayOfWeek', // 0 እሑድ - 6 ሰኞ
40 | 'z' => 'getDayOfYear', // 0 - 365
41 |
42 | 'F' => 'getTextualMonth', // መስ - ጳጉ
43 | 'M' => 'getTextualMonthShort', // መስ - ጳጉ
44 | 'n' => 'getMonth', // 1 - 13
45 | 'm' => 'getMonthTwoDigit', // 01 - 13
46 | 't' => 'getDaysInMonth', // 5 - 30
47 |
48 | 'L' => 'getLeapYearString', // 0 - 1
49 | 'Y' => 'getYear', // 2009
50 | 'y' => 'getYearShort', // 09
51 | 'a' => 'getTimeOfDay', // እኩለ፡ሌሊት-ምሽት
52 | 'A' => 'getTimeOfDay', // እኩለ፡ሌሊት-ምሽት
53 |
54 | // custom
55 | 'x' => 'getOrthodoxDay', // ልደታ - ማርቆስ
56 | 'X' => 'getOrthodoxYear', // ማቴዎስ - ዮሐንስ
57 | 'E' => 'getTextualEra', // ዓ/ዓ, ዓ/ም
58 |
59 | 'K' => 'getYearInGeez', // ፳፻፱
60 | 'V' => 'getDayInGeez', // ፪
61 |
62 | 'e' => 'getTimeZoneString', // የምስራቅ አፍሪካ ሰዓት (አዲስ አበባ)
63 | 'T' => 'getTimeZoneString', // የምስራቅ አፍሪካ ሰዓት (አዲስ አበባ)
64 |
65 | 'S' => 'getOrdinalSuffix', // ኛው
66 | 'r' => 'getFormattedDate', // ቅዳ, 01 መስ 2008 00:00:00 +0330
67 | ];
68 |
69 | const TIME_ZONES = [
70 | 'Africa/Abidjan' => 'ግሪንዊች ማዕከላዊ ሰዓት (አቢጃን)',
71 | 'Africa/Accra' => 'ግሪንዊች ማዕከላዊ ሰዓት (አክራ)',
72 | 'Africa/Addis_Ababa' => 'የምስራቅ አፍሪካ ሰዓት (አዲስ አበባ)',
73 | 'Africa/Algiers' => 'የመካከለኛው አውሮፓ ሰዓት (አልጀርስ)',
74 | 'Africa/Asmera' => 'የምስራቅ አፍሪካ ሰዓት (አስመራ)',
75 | 'Africa/Bamako' => 'ግሪንዊች ማዕከላዊ ሰዓት (ባማኮ)',
76 | 'Africa/Bangui' => 'የምዕራብ አፍሪካ ሰዓት (ባንጉኢ)',
77 | 'Africa/Banjul' => 'ግሪንዊች ማዕከላዊ ሰዓት (ባንጁል)',
78 | 'Africa/Bissau' => 'ግሪንዊች ማዕከላዊ ሰዓት (ቢሳኦ)',
79 | 'Africa/Blantyre' => 'የመካከለኛው አፍሪካ ሰዓት (ብላንታየር)',
80 | 'Africa/Brazzaville' => 'የምዕራብ አፍሪካ ሰዓት (ብራዛቪል)',
81 | 'Africa/Bujumbura' => 'የመካከለኛው አፍሪካ ሰዓት (ቡጁምብራ)',
82 | 'Africa/Cairo' => 'የምስራቃዊ አውሮፓ ሰዓት (ካይሮ)',
83 | 'Africa/Casablanca' => 'የምዕራባዊ አውሮፓ ሰዓት (ካዛብላንካ)',
84 | 'Africa/Ceuta' => 'የመካከለኛው አውሮፓ ሰዓት (ሲኡታ)',
85 | 'Africa/Conakry' => 'ግሪንዊች ማዕከላዊ ሰዓት (ኮናክሬ)',
86 | 'Africa/Dakar' => 'ግሪንዊች ማዕከላዊ ሰዓት (ዳካር)',
87 | 'Africa/Dar_es_Salaam' => 'የምስራቅ አፍሪካ ሰዓት (ዳሬ ሰላም)',
88 | 'Africa/Djibouti' => 'የምስራቅ አፍሪካ ሰዓት (ጅቡቲ)',
89 | 'Africa/Douala' => 'የምዕራብ አፍሪካ ሰዓት (ዱአላ)',
90 | 'Africa/El_Aaiun' => 'የምዕራባዊ አውሮፓ ሰዓት (ኤል አዩአን)',
91 | 'Africa/Freetown' => 'ግሪንዊች ማዕከላዊ ሰዓት (ፍሪታውን)',
92 | 'Africa/Gaborone' => 'የመካከለኛው አፍሪካ ሰዓት (ጋቦሮን)',
93 | 'Africa/Harare' => 'የመካከለኛው አፍሪካ ሰዓት (ሃራሬ)',
94 | 'Africa/Johannesburg' => 'የደቡብ አፍሪካ መደበኛ ሰዓት (ጆሃንስበርግ)',
95 | 'Africa/Juba' => 'የምስራቅ አፍሪካ ሰዓት (ጁባ)',
96 | 'Africa/Kampala' => 'የምስራቅ አፍሪካ ሰዓት (ካምፓላ)',
97 | 'Africa/Khartoum' => 'የመካከለኛው አፍሪካ ሰዓት (ካርቱም)',
98 | 'Africa/Kigali' => 'የመካከለኛው አፍሪካ ሰዓት (ኪጋሊ)',
99 | 'Africa/Kinshasa' => 'የምዕራብ አፍሪካ ሰዓት (ኪንሻሳ)',
100 | 'Africa/Lagos' => 'የምዕራብ አፍሪካ ሰዓት (ሌጎስ)',
101 | 'Africa/Libreville' => 'የምዕራብ አፍሪካ ሰዓት (ሊበርቪል)',
102 | 'Africa/Lome' => 'ግሪንዊች ማዕከላዊ ሰዓት (ሎሜ)',
103 | 'Africa/Luanda' => 'የምዕራብ አፍሪካ ሰዓት (ሉአንዳ)',
104 | 'Africa/Lubumbashi' => 'የመካከለኛው አፍሪካ ሰዓት (ሉቡምባሺ)',
105 | 'Africa/Lusaka' => 'የመካከለኛው አፍሪካ ሰዓት (ሉሳካ)',
106 | 'Africa/Malabo' => 'የምዕራብ አፍሪካ ሰዓት (ማላቡ)',
107 | 'Africa/Maputo' => 'የመካከለኛው አፍሪካ ሰዓት (ማፑቱ)',
108 | 'Africa/Maseru' => 'የደቡብ አፍሪካ መደበኛ ሰዓት (ማሴሩ)',
109 | 'Africa/Mbabane' => 'የደቡብ አፍሪካ መደበኛ ሰዓት (ምባባኔ)',
110 | 'Africa/Mogadishu' => 'የምስራቅ አፍሪካ ሰዓት (ሞቃዲሹ)',
111 | 'Africa/Monrovia' => 'ግሪንዊች ማዕከላዊ ሰዓት (ሞንሮቪያ)',
112 | 'Africa/Nairobi' => 'የምስራቅ አፍሪካ ሰዓት (ናይሮቢ)',
113 | 'Africa/Ndjamena' => 'የምዕራብ አፍሪካ ሰዓት (ንጃሜና)',
114 | 'Africa/Niamey' => 'የምዕራብ አፍሪካ ሰዓት (ኒያሜይ)',
115 | 'Africa/Nouakchott' => 'ግሪንዊች ማዕከላዊ ሰዓት (ኑአክቾት)',
116 | 'Africa/Ouagadougou' => 'ግሪንዊች ማዕከላዊ ሰዓት (ኡጋዱጉ)',
117 | 'Africa/Porto-Novo' => 'የምዕራብ አፍሪካ ሰዓት (ፖርቶ - ኖቮ)',
118 | 'Africa/Sao_Tome' => 'ግሪንዊች ማዕከላዊ ሰዓት (ሳኦ ቶሜ)',
119 | 'Africa/Tripoli' => 'የምስራቃዊ አውሮፓ ሰዓት (ትሪፖሊ)',
120 | 'Africa/Tunis' => 'የመካከለኛው አውሮፓ ሰዓት (ቱኒዝ)',
121 | 'Africa/Windhoek' => 'የመካከለኛው አፍሪካ ሰዓት (ዊንድሆክ)',
122 | 'America/Adak' => 'የሃዋይ አሌኡት ሰዓት አቆጣጠር (አዳክ)',
123 | 'America/Anchorage' => 'የአላስካ ሰዓት አቆጣጠር (አንኮራጅ)',
124 | 'America/Anguilla' => 'የአትላንቲክ የሰዓት አቆጣጠር (አንጉይላ)',
125 | 'America/Antigua' => 'የአትላንቲክ የሰዓት አቆጣጠር (አንቲጓ)',
126 | 'America/Araguaina' => 'የብራዚላዊ ሰዓት አቆጣጠር (አራጉየና)',
127 | 'America/Argentina/La_Rioja' => 'የአርጀንቲና የሰዓት አቆጣጠር (ላ ሪኦጃ)',
128 | 'America/Argentina/Rio_Gallegos' => 'የአርጀንቲና የሰዓት አቆጣጠር (ሪዮ ጋሌጎስ)',
129 | 'America/Argentina/Salta' => 'የአርጀንቲና የሰዓት አቆጣጠር (ሳልታ)',
130 | 'America/Argentina/San_Juan' => 'የአርጀንቲና የሰዓት አቆጣጠር (ሳን ጁአን)',
131 | 'America/Argentina/San_Luis' => 'የአርጀንቲና ምስራቃዊ ሰዓት አቆጣጠር (ሳን ሊውስ)',
132 | 'America/Argentina/Tucuman' => 'የአርጀንቲና የሰዓት አቆጣጠር (ቱኩማን)',
133 | 'America/Argentina/Ushuaia' => 'የአርጀንቲና የሰዓት አቆጣጠር (ኡሹአኢ)',
134 | 'America/Aruba' => 'የአትላንቲክ የሰዓት አቆጣጠር (አሩባ)',
135 | 'America/Asuncion' => 'የፓራጓይ ሰዓት (አሱንሲዮን)',
136 | 'America/Bahia' => 'የብራዚላዊ ሰዓት አቆጣጠር (ባሂአ)',
137 | 'America/Bahia_Banderas' => 'የሰሜን አሜሪካ የመካከለኛ ሰዓት አቆጣጠር (ባሂያ ባንደራስ)',
138 | 'America/Barbados' => 'የአትላንቲክ የሰዓት አቆጣጠር (ባርቤዶስ)',
139 | 'America/Belem' => 'የብራዚላዊ ሰዓት አቆጣጠር (ቤለም)',
140 | 'America/Belize' => 'የሰሜን አሜሪካ የመካከለኛ ሰዓት አቆጣጠር (ቤሊዝ)',
141 | 'America/Blanc-Sablon' => 'የአትላንቲክ የሰዓት አቆጣጠር (ብላንክ- ሳብሎን)',
142 | 'America/Boa_Vista' => 'የአማዞን ሰዓት አቆጣጠር (ቦአ ቪስታ)',
143 | 'America/Bogota' => 'የኮሎምቢያ ሰዓት (ቦጎታ)',
144 | 'America/Boise' => 'የተራራ የሰዓት አቆጣጠር (ቦይዝ)',
145 | 'America/Buenos_Aires' => 'የአርጀንቲና የሰዓት አቆጣጠር (ቦነስ አይረስ)',
146 | 'America/Cambridge_Bay' => 'የተራራ የሰዓት አቆጣጠር (ካምብሪጅ ቤይ)',
147 | 'America/Campo_Grande' => 'የአማዞን ሰዓት አቆጣጠር (ካምፖ ግራንዴ)',
148 | 'America/Cancun' => 'ምስራቃዊ ሰዓት አቆጣጠር (ካንኩን)',
149 | 'America/Caracas' => 'የቬኔዝዌላ ሰዓት (ካራካስ)',
150 | 'America/Catamarca' => 'የአርጀንቲና የሰዓት አቆጣጠር (ካታማርካ)',
151 | 'America/Cayenne' => 'የፈረንሳይ ጉያና ሰዓት (ካይንኤ)',
152 | 'America/Cayman' => 'ምስራቃዊ ሰዓት አቆጣጠር (ካይማን)',
153 | 'America/Chicago' => 'የሰሜን አሜሪካ የመካከለኛ ሰዓት አቆጣጠር (ቺካጎ)',
154 | 'America/Chihuahua' => 'የሜክሲኮ ፓሲፊክ ሰዓት አቆጣጠር (ቺሁዋውአ)',
155 | 'America/Coral_Harbour' => 'ምስራቃዊ ሰዓት አቆጣጠር (አቲኮካን)',
156 | 'America/Cordoba' => 'የአርጀንቲና የሰዓት አቆጣጠር (ኮርዶባ)',
157 | 'America/Costa_Rica' => 'የሰሜን አሜሪካ የመካከለኛ ሰዓት አቆጣጠር (ኮስታሪካ)',
158 | 'America/Creston' => 'የተራራ የሰዓት አቆጣጠር (ክረስተን)',
159 | 'America/Cuiaba' => 'የአማዞን ሰዓት አቆጣጠር (ኩየአባ)',
160 | 'America/Curacao' => 'የአትላንቲክ የሰዓት አቆጣጠር (ኩራሳዎ)',
161 | 'America/Danmarkshavn' => 'ግሪንዊች ማዕከላዊ ሰዓት (ዳንማርክሻቭን)',
162 | 'America/Dawson' => 'የፓስፊክ ሰዓት አቆጣጠር (ዳውሰን)',
163 | 'America/Dawson_Creek' => 'የተራራ የሰዓት አቆጣጠር (ዳውሰን ክሬክ)',
164 | 'America/Denver' => 'የተራራ የሰዓት አቆጣጠር (ዴንቨር)',
165 | 'America/Detroit' => 'ምስራቃዊ ሰዓት አቆጣጠር (ዲትሮይት)',
166 | 'America/Dominica' => 'የአትላንቲክ የሰዓት አቆጣጠር (ዶሜኒካ)',
167 | 'America/Edmonton' => 'የተራራ የሰዓት አቆጣጠር (ኤድመንተን)',
168 | 'America/Eirunepe' => 'ብራዚል ጊዜ (ኢሩኔፕ)',
169 | 'America/El_Salvador' => 'የሰሜን አሜሪካ የመካከለኛ ሰዓት አቆጣጠር (ኤልሳልቫዶር)',
170 | 'America/Fort_Nelson' => 'የተራራ የሰዓት አቆጣጠር (ፎርት ኔልሰን)',
171 | 'America/Fortaleza' => 'የብራዚላዊ ሰዓት አቆጣጠር (ፎርታሌዛ)',
172 | 'America/Glace_Bay' => 'የአትላንቲክ የሰዓት አቆጣጠር (ግሌስ ቤይ)',
173 | 'America/Godthab' => 'የምዕራብ ግሪንላንድ ሰዓት (ጋድታብ)',
174 | 'America/Goose_Bay' => 'የአትላንቲክ የሰዓት አቆጣጠር (ጉዝ ቤይ)',
175 | 'America/Grand_Turk' => 'ምስራቃዊ ሰዓት አቆጣጠር (ግራንድ ተርክ)',
176 | 'America/Grenada' => 'የአትላንቲክ የሰዓት አቆጣጠር (ግሬናዳ)',
177 | 'America/Guadeloupe' => 'የአትላንቲክ የሰዓት አቆጣጠር (ጕዳሉፕ)',
178 | 'America/Guatemala' => 'የሰሜን አሜሪካ የመካከለኛ ሰዓት አቆጣጠር (ጓቲማላ)',
179 | 'America/Guayaquil' => 'የኢኳዶር ሰዓት (ጉያኩይል)',
180 | 'America/Guyana' => 'የጉያና ሰዓት',
181 | 'America/Halifax' => 'የአትላንቲክ የሰዓት አቆጣጠር (ሃሊፋክስ)',
182 | 'America/Havana' => 'ኩባ ሰዓት (ሃቫና)',
183 | 'America/Hermosillo' => 'የሜክሲኮ ፓሲፊክ ሰዓት አቆጣጠር (ኸርሞዚሎ)',
184 | 'America/Indiana/Knox' => 'የሰሜን አሜሪካ የመካከለኛ ሰዓት አቆጣጠር (ኖክስ, ኢንዲያና)',
185 | 'America/Indiana/Marengo' => 'ምስራቃዊ ሰዓት አቆጣጠር (ማሬንጎ, ኢንዲያና)',
186 | 'America/Indiana/Petersburg' => 'ምስራቃዊ ሰዓት አቆጣጠር (ፒተርስበርግ, ኢንዲያና)',
187 | 'America/Indiana/Tell_City' => 'የሰሜን አሜሪካ የመካከለኛ ሰዓት አቆጣጠር (ቴል ከተማ, ኢንዲያና)',
188 | 'America/Indiana/Vevay' => 'ምስራቃዊ ሰዓት አቆጣጠር (ቪቫይ, ኢንዲያና)',
189 | 'America/Indiana/Vincennes' => 'ምስራቃዊ ሰዓት አቆጣጠር (ቪንቼንስ, ኢንዲያና)',
190 | 'America/Indiana/Winamac' => 'ምስራቃዊ ሰዓት አቆጣጠር (ዊናማክ, ኢንዲያና)',
191 | 'America/Indianapolis' => 'ምስራቃዊ ሰዓት አቆጣጠር (ኢንዲያናፖሊስ)',
192 | 'America/Inuvik' => 'የተራራ የሰዓት አቆጣጠር (ኢኑቪክ)',
193 | 'America/Iqaluit' => 'ምስራቃዊ ሰዓት አቆጣጠር (ኢኳሊውት)',
194 | 'America/Jamaica' => 'ምስራቃዊ ሰዓት አቆጣጠር (ጃማይካ)',
195 | 'America/Jujuy' => 'የአርጀንቲና የሰዓት አቆጣጠር (ጁጁይ)',
196 | 'America/Juneau' => 'የአላስካ ሰዓት አቆጣጠር (ጁኒዩ)',
197 | 'America/Kentucky/Monticello' => 'ምስራቃዊ ሰዓት አቆጣጠር (ሞንቲሴሎ, ኪንታኪ)',
198 | 'America/Kralendijk' => 'የአትላንቲክ የሰዓት አቆጣጠር (ክራለንዲይክ)',
199 | 'America/La_Paz' => 'የቦሊቪያ ሰዓት (ላ ፓዝ)',
200 | 'America/Lima' => 'የፔሩ ሰዓት (ሊማ)',
201 | 'America/Los_Angeles' => 'የፓስፊክ ሰዓት አቆጣጠር (ሎስ አንጀለስ)',
202 | 'America/Louisville' => 'ምስራቃዊ ሰዓት አቆጣጠር (ሊውስቪል)',
203 | 'America/Lower_Princes' => 'የአትላንቲክ የሰዓት አቆጣጠር (የታችኛው ልዑል ሩብ)',
204 | 'America/Maceio' => 'የብራዚላዊ ሰዓት አቆጣጠር (ሜሲኦ)',
205 | 'America/Managua' => 'የሰሜን አሜሪካ የመካከለኛ ሰዓት አቆጣጠር (ማናጉአ)',
206 | 'America/Manaus' => 'የአማዞን ሰዓት አቆጣጠር (ማናኡስ)',
207 | 'America/Marigot' => 'የአትላንቲክ የሰዓት አቆጣጠር (ማርጎት)',
208 | 'America/Martinique' => 'የአትላንቲክ የሰዓት አቆጣጠር (ማርቲኒክ)',
209 | 'America/Matamoros' => 'የሰሜን አሜሪካ የመካከለኛ ሰዓት አቆጣጠር (ማታሞሮስ)',
210 | 'America/Mazatlan' => 'የሜክሲኮ ፓሲፊክ ሰዓት አቆጣጠር (ማዛትላን)',
211 | 'America/Mendoza' => 'የአርጀንቲና የሰዓት አቆጣጠር (ሜንዶዛ)',
212 | 'America/Menominee' => 'የሰሜን አሜሪካ የመካከለኛ ሰዓት አቆጣጠር (ሜኖሚኒ)',
213 | 'America/Merida' => 'የሰሜን አሜሪካ የመካከለኛ ሰዓት አቆጣጠር (ሜሪዳ)',
214 | 'America/Metlakatla' => 'የአላስካ ሰዓት አቆጣጠር (መትላካትላ)',
215 | 'America/Mexico_City' => 'የሰሜን አሜሪካ የመካከለኛ ሰዓት አቆጣጠር (ሜክሲኮ ከተማ)',
216 | 'America/Miquelon' => 'ቅዱስ የፒዬር እና ሚኴሎን ሰዓት (ሚኮውሎን)',
217 | 'America/Moncton' => 'የአትላንቲክ የሰዓት አቆጣጠር (ሞንክቶን)',
218 | 'America/Monterrey' => 'የሰሜን አሜሪካ የመካከለኛ ሰዓት አቆጣጠር (ሞንተርሬይ)',
219 | 'America/Montevideo' => 'የኡራጓይ ሰዓት (ሞንቴቪድዮ)',
220 | 'America/Montreal' => 'ካናዳ ጊዜ (Montreal)',
221 | 'America/Montserrat' => 'የአትላንቲክ የሰዓት አቆጣጠር (ሞንትሴራት)',
222 | 'America/Nassau' => 'ምስራቃዊ ሰዓት አቆጣጠር (ናሳው)',
223 | 'America/New_York' => 'ምስራቃዊ ሰዓት አቆጣጠር (ኒውዮርክ)',
224 | 'America/Nipigon' => 'ምስራቃዊ ሰዓት አቆጣጠር (ኒፒጎን)',
225 | 'America/Nome' => 'የአላስካ ሰዓት አቆጣጠር (ኖሜ)',
226 | 'America/Noronha' => 'የኖሮንሃ ሰዓት አቆጣጠር (ኖሮኛ)',
227 | 'America/North_Dakota/Beulah' => 'የሰሜን አሜሪካ የመካከለኛ ሰዓት አቆጣጠር (ቤኡላህ, ሰሜን ዳኮታ)',
228 | 'America/North_Dakota/Center' => 'የሰሜን አሜሪካ የመካከለኛ ሰዓት አቆጣጠር (መካከለኛ, ሰሜን ዳኮታ)',
229 | 'America/North_Dakota/New_Salem' => 'የሰሜን አሜሪካ የመካከለኛ ሰዓት አቆጣጠር (አዲስ ሳሌም, ሰሜን ዳኮታ)',
230 | 'America/Ojinaga' => 'የተራራ የሰዓት አቆጣጠር (ኦዪናጋ)',
231 | 'America/Panama' => 'ምስራቃዊ ሰዓት አቆጣጠር (ፓናማ)',
232 | 'America/Pangnirtung' => 'ምስራቃዊ ሰዓት አቆጣጠር (ፓንግኒርተንግ)',
233 | 'America/Paramaribo' => 'የሱሪናም ሰዓት (ፓራማሪቦ)',
234 | 'America/Phoenix' => 'የተራራ የሰዓት አቆጣጠር (ፊኒክስ)',
235 | 'America/Port-au-Prince' => 'ምስራቃዊ ሰዓት አቆጣጠር (ፖርት ኦ ፕሪንስ)',
236 | 'America/Port_of_Spain' => 'የአትላንቲክ የሰዓት አቆጣጠር (የእስፔን ወደብ)',
237 | 'America/Porto_Velho' => 'የአማዞን ሰዓት አቆጣጠር (ፔትሮ ቬልሆ)',
238 | 'America/Puerto_Rico' => 'የአትላንቲክ የሰዓት አቆጣጠር (ፖርቶሪኮ)',
239 | 'America/Punta_Arenas' => 'የቺሊ ሰዓት (ፑንታ አሬናስ)',
240 | 'America/Rainy_River' => 'የሰሜን አሜሪካ የመካከለኛ ሰዓት አቆጣጠር (ሬኒ ሪቨር)',
241 | 'America/Rankin_Inlet' => 'የሰሜን አሜሪካ የመካከለኛ ሰዓት አቆጣጠር (ራንኪን ኢንሌት)',
242 | 'America/Recife' => 'የብራዚላዊ ሰዓት አቆጣጠር (ረሲፍ)',
243 | 'America/Regina' => 'የሰሜን አሜሪካ የመካከለኛ ሰዓት አቆጣጠር (ረጂና)',
244 | 'America/Resolute' => 'የሰሜን አሜሪካ የመካከለኛ ሰዓት አቆጣጠር (ሪዞሊዩት)',
245 | 'America/Rio_Branco' => 'ብራዚል ጊዜ (ሪዮ ብራንኮ)',
246 | 'America/Santa_Isabel' => 'ሰሜናዊ ምእራብ የሜክሲኮ ሰዓት አቆጣጠር (ሳንታ ኢዛቤል)',
247 | 'America/Santarem' => 'የብራዚላዊ ሰዓት አቆጣጠር (ሳንታሬም)',
248 | 'America/Santiago' => 'የቺሊ ሰዓት (ሳንቲያጎ)',
249 | 'America/Santo_Domingo' => 'የአትላንቲክ የሰዓት አቆጣጠር (ሳንቶ ዶሚንጎ)',
250 | 'America/Sao_Paulo' => 'የብራዚላዊ ሰዓት አቆጣጠር (ሳኦ ፖሎ)',
251 | 'America/Scoresbysund' => 'የምስራቅ ግሪንላንድ ሰዓት (ስኮርስባይሰንድ)',
252 | 'America/Sitka' => 'የአላስካ ሰዓት አቆጣጠር (ሲትካ)',
253 | 'America/St_Barthelemy' => 'የአትላንቲክ የሰዓት አቆጣጠር (ቅድስት ቤርተሎሜ)',
254 | 'America/St_Johns' => 'የኒውፋውንድላንድ የሰዓት አቆጣጠር (ቅዱስ ዮሐንስ)',
255 | 'America/St_Kitts' => 'የአትላንቲክ የሰዓት አቆጣጠር (ቅዱስ ኪትስ)',
256 | 'America/St_Lucia' => 'የአትላንቲክ የሰዓት አቆጣጠር (ቅድስት ሉሲያ)',
257 | 'America/St_Thomas' => 'የአትላንቲክ የሰዓት አቆጣጠር (ቅዱስ ቶማስ)',
258 | 'America/St_Vincent' => 'የአትላንቲክ የሰዓት አቆጣጠር (ቅዱስ ቪንሰንት)',
259 | 'America/Swift_Current' => 'የሰሜን አሜሪካ የመካከለኛ ሰዓት አቆጣጠር (የሐዋላ ገንዘብ)',
260 | 'America/Tegucigalpa' => 'የሰሜን አሜሪካ የመካከለኛ ሰዓት አቆጣጠር (ቴጉሲጋልፓ)',
261 | 'America/Thule' => 'የአትላንቲክ የሰዓት አቆጣጠር (ቱሌ)',
262 | 'America/Thunder_Bay' => 'ምስራቃዊ ሰዓት አቆጣጠር (ተንደር ቤይ)',
263 | 'America/Tijuana' => 'የፓስፊክ ሰዓት አቆጣጠር (ቲጁአና)',
264 | 'America/Toronto' => 'ምስራቃዊ ሰዓት አቆጣጠር (ቶሮንቶ)',
265 | 'America/Tortola' => 'የአትላንቲክ የሰዓት አቆጣጠር (ቶርቶላ)',
266 | 'America/Vancouver' => 'የፓስፊክ ሰዓት አቆጣጠር (ቫንኮቨር)',
267 | 'America/Whitehorse' => 'የፓስፊክ ሰዓት አቆጣጠር (ኋይትሆርስ)',
268 | 'America/Winnipeg' => 'የሰሜን አሜሪካ የመካከለኛ ሰዓት አቆጣጠር (ዊኒፔግ)',
269 | 'America/Yakutat' => 'የአላስካ ሰዓት አቆጣጠር (ያኩታት)',
270 | 'America/Yellowknife' => 'የተራራ የሰዓት አቆጣጠር (የሎውናይፍ)',
271 | 'Antarctica/Casey' => 'የምስራቃዊ አውስትራሊያ ሰዓት አቆጣጠር (ካዚይ)',
272 | 'Antarctica/Davis' => 'የዴቪስ ሰዓት (ዳቪስ)',
273 | 'Antarctica/DumontDUrville' => 'የዱሞንት-ዱርቪል ሰዓት (ደሞንት ዲኡርቪል)',
274 | 'Antarctica/Macquarie' => 'የማከሪ ደሴት ሰዓት',
275 | 'Antarctica/Mawson' => 'የማውሰን ሰዓት (ናውሰን)',
276 | 'Antarctica/McMurdo' => 'የኒው ዚላንድ ሰዓት (ማክመርዶ)',
277 | 'Antarctica/Palmer' => 'የቺሊ ሰዓት (ፓልመር)',
278 | 'Antarctica/Rothera' => 'የሮቴራ ሰዓት',
279 | 'Antarctica/Syowa' => 'የሲዮዋ ሰዓት (ስዮዋ)',
280 | 'Antarctica/Troll' => 'ግሪንዊች ማዕከላዊ ሰዓት (ትሮል)',
281 | 'Antarctica/Vostok' => 'የቮስቶክ ሰዓት (ቭስቶክ)',
282 | 'Arctic/Longyearbyen' => 'የመካከለኛው አውሮፓ ሰዓት (ሎንግይርባየን)',
283 | 'Asia/Aden' => 'የዓረቢያ ሰዓት (ኤደን)',
284 | 'Asia/Almaty' => 'የምስራቅ ካዛኪስታን ሰዓት (አልማትይ)',
285 | 'Asia/Amman' => 'የምስራቃዊ አውሮፓ ሰዓት (አማን)',
286 | 'Asia/Anadyr' => 'የአናድይር ሰዓት አቆጣጠር',
287 | 'Asia/Aqtau' => 'የምዕራብ ካዛኪስታን ሰዓት (አኩታኡ)',
288 | 'Asia/Aqtobe' => 'የምዕራብ ካዛኪስታን ሰዓት (አኩቶቤ)',
289 | 'Asia/Ashgabat' => 'የቱርክመኒስታን ሰዓት (አሽጋባት)',
290 | 'Asia/Atyrau' => 'የምዕራብ ካዛኪስታን ሰዓት (አትይራኡ)',
291 | 'Asia/Baghdad' => 'የዓረቢያ ሰዓት (ባግዳድ)',
292 | 'Asia/Bahrain' => 'የዓረቢያ ሰዓት (ባህሬን)',
293 | 'Asia/Baku' => 'የአዘርባጃን ሰዓት (ባኩ)',
294 | 'Asia/Bangkok' => 'የኢንዶቻይና ሰዓት (ባንኮክ)',
295 | 'Asia/Barnaul' => 'ሩስያ ጊዜ (ባርናኡል)',
296 | 'Asia/Beirut' => 'የምስራቃዊ አውሮፓ ሰዓት (ቤሩት)',
297 | 'Asia/Bishkek' => 'የኪርጊስታን ሰዓት (ቢሽኬክ)',
298 | 'Asia/Brunei' => 'የብሩኔይ ዳሩሳላም ሰዓት (ብሩናይ)',
299 | 'Asia/Calcutta' => 'የህንድ መደበኛ ሰዓት (ኮልካታ)',
300 | 'Asia/Chita' => 'ያኩትስክ የሰዓት አቆጣጠር (ቺታ)',
301 | 'Asia/Choibalsan' => 'የቾይባልሳ ሰዓት አቆጣጠር (ቾይባልሳን)',
302 | 'Asia/Colombo' => 'የህንድ መደበኛ ሰዓት (ኮሎምቦ)',
303 | 'Asia/Damascus' => 'የምስራቃዊ አውሮፓ ሰዓት (ደማስቆ)',
304 | 'Asia/Dhaka' => 'የባንግላዴሽ ሰዓት (ዳካ)',
305 | 'Asia/Dili' => 'የምስራቅ ቲሞር ሰዓት (ዲሊ)',
306 | 'Asia/Dubai' => 'የባህረሰላጤ መደበኛ ሰዓት (ዱባይ)',
307 | 'Asia/Dushanbe' => 'የታጂኪስታን ሰዓት (ደሻንቤ)',
308 | 'Asia/Famagusta' => 'የምስራቃዊ አውሮፓ ሰዓት (ፋማጉስታ)',
309 | 'Asia/Gaza' => 'የምስራቃዊ አውሮፓ ሰዓት (ጋዛ)',
310 | 'Asia/Hebron' => 'የምስራቃዊ አውሮፓ ሰዓት (ኬብሮን)',
311 | 'Asia/Hong_Kong' => 'የሆንግ ኮንግ ሰዓት',
312 | 'Asia/Hovd' => 'የሆቭድ ሰዓት አቆጣጠር',
313 | 'Asia/Irkutsk' => 'የኢርኩትስክ ሰዓት አቆጣጠር',
314 | 'Asia/Jakarta' => 'የምዕራባዊ ኢንዶኔዢያ ሰዓት (ጃካርታ)',
315 | 'Asia/Jayapura' => 'የምስራቃዊ ኢንዶኔዢያ ሰዓት (ጃያፑራ)',
316 | 'Asia/Jerusalem' => 'የእስራኤል ሰዓት (እየሩሳሌም)',
317 | 'Asia/Kabul' => 'የአፍጋኒስታን ሰዓት (ካቡል)',
318 | 'Asia/Kamchatka' => 'የካምቻትካ ሰዓት አቆጣጠር',
319 | 'Asia/Karachi' => 'የፓኪስታን ሰዓት (ካራቺ)',
320 | 'Asia/Katmandu' => 'የኔፓል ሰዓት (ካትማንዱ)',
321 | 'Asia/Khandyga' => 'ያኩትስክ የሰዓት አቆጣጠር (ካንዲጋ)',
322 | 'Asia/Krasnoyarsk' => 'የክራስኖያርስክ ሰዓት አቆጣጠር',
323 | 'Asia/Kuala_Lumpur' => 'የማሌይዢያ ሰዓት (ኩዋላ ላምፑር)',
324 | 'Asia/Kuching' => 'የማሌይዢያ ሰዓት (ኩቺንግ)',
325 | 'Asia/Kuwait' => 'የዓረቢያ ሰዓት (ኩዌት)',
326 | 'Asia/Macau' => 'የቻይና ሰዓት (ማካኡ)',
327 | 'Asia/Magadan' => 'የማጋዳን የሰዓት አቆጣጠር',
328 | 'Asia/Makassar' => 'የመካከለኛው ኢንዶኔዢያ ሰዓት (ማካሳር)',
329 | 'Asia/Manila' => 'የፊሊፒን ሰዓት (ማኒላ)',
330 | 'Asia/Muscat' => 'የባህረሰላጤ መደበኛ ሰዓት (ሙስካት)',
331 | 'Asia/Nicosia' => 'የምስራቃዊ አውሮፓ ሰዓት (ኒኮሲአ)',
332 | 'Asia/Novokuznetsk' => 'የክራስኖያርስክ ሰዓት አቆጣጠር (ኖቮኩትዝኔክ)',
333 | 'Asia/Novosibirsk' => 'የኖቮሲብሪስክ የሰዓት አቆጣጠር (ኖቮሲቢሪስክ)',
334 | 'Asia/Omsk' => 'የኦምስክ የሰዓት አቆጣጠር',
335 | 'Asia/Oral' => 'የምዕራብ ካዛኪስታን ሰዓት (ኦራል)',
336 | 'Asia/Phnom_Penh' => 'የኢንዶቻይና ሰዓት (ፍኖም ፔንህ)',
337 | 'Asia/Pontianak' => 'የምዕራባዊ ኢንዶኔዢያ ሰዓት (ፖንቲአናክ)',
338 | 'Asia/Pyongyang' => 'የኮሪያ ሰዓት (ፕዮንግያንግ)',
339 | 'Asia/Qatar' => 'የዓረቢያ ሰዓት (ኳታር)',
340 | 'Asia/Qostanay' => 'የምስራቅ ካዛኪስታን ሰዓት (ኮስታናይ)',
341 | 'Asia/Qyzylorda' => 'የምዕራብ ካዛኪስታን ሰዓት (ኩይዚሎርዳ)',
342 | 'Asia/Rangoon' => 'የሚያንማር ሰዓት (ያንጎን)',
343 | 'Asia/Riyadh' => 'የዓረቢያ ሰዓት (ሪያድ)',
344 | 'Asia/Saigon' => 'የኢንዶቻይና ሰዓት (ሆ ቺ ሚንህ ከተማ)',
345 | 'Asia/Sakhalin' => 'የሳክሃሊን ሰዓት አቆጣጠር',
346 | 'Asia/Samarkand' => 'የኡዝቤኪስታን ሰዓት (ሳማርካንድ)',
347 | 'Asia/Seoul' => 'የኮሪያ ሰዓት (ሴኦል)',
348 | 'Asia/Shanghai' => 'የቻይና ሰዓት (ሻንጋይ)',
349 | 'Asia/Singapore' => 'የሲንጋፒር መደበኛ ሰዓት (ሲንጋፖር)',
350 | 'Asia/Srednekolymsk' => 'የማጋዳን የሰዓት አቆጣጠር (ስሬድኔስኮልምስክ)',
351 | 'Asia/Taipei' => 'የታይፔይ ሰዓት (ታይፓይ)',
352 | 'Asia/Tashkent' => 'የኡዝቤኪስታን ሰዓት (ታሽኬንት)',
353 | 'Asia/Tbilisi' => 'የጂዮርጂያ ሰዓት (ትብሊሲ)',
354 | 'Asia/Tehran' => 'የኢራን ሰዓት (ቴህራን)',
355 | 'Asia/Thimphu' => 'የቡታን ሰዓት (ቲምፉ)',
356 | 'Asia/Tokyo' => 'የጃፓን ሰዓት (ቶኪዮ)',
357 | 'Asia/Tomsk' => 'ሩስያ ጊዜ (ቶምስክ)',
358 | 'Asia/Ulaanbaatar' => 'የኡላን ባቶር ጊዜ (ኡላአንባአታር)',
359 | 'Asia/Urumqi' => 'ቻይና ጊዜ (ኡሩምኪ)',
360 | 'Asia/Ust-Nera' => 'የቭላዲቮስቶክ የሰዓት አቆጣጠር (ኡስት-ኔራ)',
361 | 'Asia/Vientiane' => 'የኢንዶቻይና ሰዓት (ቬንቲአን)',
362 | 'Asia/Vladivostok' => 'የቭላዲቮስቶክ የሰዓት አቆጣጠር',
363 | 'Asia/Yakutsk' => 'ያኩትስክ የሰዓት አቆጣጠር',
364 | 'Asia/Yekaterinburg' => 'የየካተሪንበርግ ሰዓት አቆጣጠር',
365 | 'Asia/Yerevan' => 'የአርመኒያ ሰዓት (ይሬቫን)',
366 | 'Atlantic/Azores' => 'የአዞረስ ሰዓት',
367 | 'Atlantic/Bermuda' => 'የአትላንቲክ የሰዓት አቆጣጠር (ቤርሙዳ)',
368 | 'Atlantic/Canary' => 'የምዕራባዊ አውሮፓ ሰዓት (ካናሪ)',
369 | 'Atlantic/Cape_Verde' => 'የኬፕ ቨርዴ ሰዓት (ኬፕ ቬርደ)',
370 | 'Atlantic/Faeroe' => 'የምዕራባዊ አውሮፓ ሰዓት (ፋሮእ)',
371 | 'Atlantic/Madeira' => 'የምዕራባዊ አውሮፓ ሰዓት (ማዴራ)',
372 | 'Atlantic/Reykjavik' => 'ግሪንዊች ማዕከላዊ ሰዓት (ሬይክጃቪክ)',
373 | 'Atlantic/South_Georgia' => 'የደቡብ ጂዮርጂያ ሰዓት (ደቡብ ጆርጂያ)',
374 | 'Atlantic/St_Helena' => 'ግሪንዊች ማዕከላዊ ሰዓት (ቅድስት ሄለና)',
375 | 'Atlantic/Stanley' => 'የፋልክላንድ ደሴቶች ሰዓት (ስታንሌይ)',
376 | 'Australia/Adelaide' => 'የመካከለኛው አውስትራሊያ ሰዓት አቆጣጠር (አዴሌእድ)',
377 | 'Australia/Brisbane' => 'የምዕራባዊ አውስትራሊያ የሰዓት አቆጣጠር (ብሪስቤን)',
378 | 'Australia/Broken_Hill' => 'የመካከለኛው አውስትራሊያ ሰዓት አቆጣጠር (ብሮክን ሂል)',
379 | 'Australia/Currie' => 'የምዕራባዊ አውስትራሊያ የሰዓት አቆጣጠር (ከሪ)',
380 | 'Australia/Darwin' => 'የመካከለኛው አውስትራሊያ ሰዓት አቆጣጠር (ዳርዊን)',
381 | 'Australia/Eucla' => 'የአውስትራሊያ መካከለኛ ምስራቃዊ ሰዓት አቆጣጠር (ኡክላ)',
382 | 'Australia/Hobart' => 'የምዕራባዊ አውስትራሊያ የሰዓት አቆጣጠር (ሆባርት)',
383 | 'Australia/Lindeman' => 'የምዕራባዊ አውስትራሊያ የሰዓት አቆጣጠር (ሊንድማን)',
384 | 'Australia/Lord_Howe' => 'የሎርድ ሆዌ የሰዓት አቆጣጠር (ሎርድ ሆዊ)',
385 | 'Australia/Melbourne' => 'የምዕራባዊ አውስትራሊያ የሰዓት አቆጣጠር (ሜልቦርን)',
386 | 'Australia/Perth' => 'የምስራቃዊ አውስትራሊያ ሰዓት አቆጣጠር (ፐርዝ)',
387 | 'Australia/Sydney' => 'የምዕራባዊ አውስትራሊያ የሰዓት አቆጣጠር (ሲድኒ)',
388 | 'CST6CDT' => 'የሰሜን አሜሪካ የመካከለኛ ሰዓት አቆጣጠር',
389 | 'EST5EDT' => 'ምስራቃዊ ሰዓት አቆጣጠር',
390 | 'Etc/GMT' => 'ግሪንዊች ማዕከላዊ ሰዓት',
391 | 'Etc/UTC' => 'የተቀነባበረ ሁለገብ ሰዓት',
392 | 'Europe/Amsterdam' => 'የመካከለኛው አውሮፓ ሰዓት (አምስተርዳም)',
393 | 'Europe/Andorra' => 'የመካከለኛው አውሮፓ ሰዓት (አንዶራ)',
394 | 'Europe/Astrakhan' => 'የሞስኮ ሰዓት አቆጣጠር (አስትራክሃን)',
395 | 'Europe/Athens' => 'የምስራቃዊ አውሮፓ ሰዓት (አቴንስ)',
396 | 'Europe/Belgrade' => 'የመካከለኛው አውሮፓ ሰዓት (ቤልግሬድ)',
397 | 'Europe/Berlin' => 'የመካከለኛው አውሮፓ ሰዓት (በርሊን)',
398 | 'Europe/Bratislava' => 'የመካከለኛው አውሮፓ ሰዓት (ብራቲስላቫ)',
399 | 'Europe/Brussels' => 'የመካከለኛው አውሮፓ ሰዓት (ብራሰልስ)',
400 | 'Europe/Bucharest' => 'የምስራቃዊ አውሮፓ ሰዓት (ቡካሬስት)',
401 | 'Europe/Budapest' => 'የመካከለኛው አውሮፓ ሰዓት (ቡዳፔስት)',
402 | 'Europe/Busingen' => 'የመካከለኛው አውሮፓ ሰዓት (ቡሲንገን)',
403 | 'Europe/Chisinau' => 'የምስራቃዊ አውሮፓ ሰዓት (ቺስናኡ)',
404 | 'Europe/Copenhagen' => 'የመካከለኛው አውሮፓ ሰዓት (ኮፐንሃገን)',
405 | 'Europe/Dublin' => 'ግሪንዊች ማዕከላዊ ሰዓት (ደብሊን)',
406 | 'Europe/Gibraltar' => 'የመካከለኛው አውሮፓ ሰዓት (ጂብራልታር)',
407 | 'Europe/Guernsey' => 'ግሪንዊች ማዕከላዊ ሰዓት (ጉርነሲ)',
408 | 'Europe/Helsinki' => 'የምስራቃዊ አውሮፓ ሰዓት (ሄልሲንኪ)',
409 | 'Europe/Isle_of_Man' => 'ግሪንዊች ማዕከላዊ ሰዓት (አይስል ኦፍ ማን)',
410 | 'Europe/Istanbul' => 'ቱርክ ጊዜ (ኢስታንቡል)',
411 | 'Europe/Jersey' => 'ግሪንዊች ማዕከላዊ ሰዓት (ጀርሲ)',
412 | 'Europe/Kaliningrad' => 'የምስራቃዊ አውሮፓ ሰዓት (ካሊኒንግራድ)',
413 | 'Europe/Kiev' => 'የምስራቃዊ አውሮፓ ሰዓት (ኪየቭ)',
414 | 'Europe/Kirov' => 'ሩስያ ጊዜ (ኪሮቭ)',
415 | 'Europe/Lisbon' => 'የምዕራባዊ አውሮፓ ሰዓት (ሊዝበን)',
416 | 'Europe/Ljubljana' => 'የመካከለኛው አውሮፓ ሰዓት (ልጁብልጃና)',
417 | 'Europe/London' => 'ግሪንዊች ማዕከላዊ ሰዓት (ለንደን)',
418 | 'Europe/Luxembourg' => 'የመካከለኛው አውሮፓ ሰዓት (ሉክሰምበርግ)',
419 | 'Europe/Madrid' => 'የመካከለኛው አውሮፓ ሰዓት (ማድሪድ)',
420 | 'Europe/Malta' => 'የመካከለኛው አውሮፓ ሰዓት (ማልታ)',
421 | 'Europe/Mariehamn' => 'የምስራቃዊ አውሮፓ ሰዓት (ሜሪሃምን)',
422 | 'Europe/Minsk' => 'የሞስኮ ሰዓት አቆጣጠር (ሚንስክ)',
423 | 'Europe/Monaco' => 'የመካከለኛው አውሮፓ ሰዓት (ሞናኮ)',
424 | 'Europe/Moscow' => 'የሞስኮ ሰዓት አቆጣጠር',
425 | 'Europe/Oslo' => 'የመካከለኛው አውሮፓ ሰዓት (ኦስሎ)',
426 | 'Europe/Paris' => 'የመካከለኛው አውሮፓ ሰዓት (ፓሪስ)',
427 | 'Europe/Podgorica' => 'የመካከለኛው አውሮፓ ሰዓት (ፖድጎሪካ)',
428 | 'Europe/Prague' => 'የመካከለኛው አውሮፓ ሰዓት (ፕራግ)',
429 | 'Europe/Riga' => 'የምስራቃዊ አውሮፓ ሰዓት (ሪጋ)',
430 | 'Europe/Rome' => 'የመካከለኛው አውሮፓ ሰዓት (ሮም)',
431 | 'Europe/Samara' => 'የሳማራ ሰዓት አቆጣጠር',
432 | 'Europe/San_Marino' => 'የመካከለኛው አውሮፓ ሰዓት (ሳን ማሪኖ)',
433 | 'Europe/Sarajevo' => 'የመካከለኛው አውሮፓ ሰዓት (ሳሪየቮ)',
434 | 'Europe/Saratov' => 'የሞስኮ ሰዓት አቆጣጠር (ሳራቶቭ)',
435 | 'Europe/Simferopol' => 'የሞስኮ ሰዓት አቆጣጠር (ሲምፈሮፖል)',
436 | 'Europe/Skopje' => 'የመካከለኛው አውሮፓ ሰዓት (ስኮፕየ)',
437 | 'Europe/Sofia' => 'የምስራቃዊ አውሮፓ ሰዓት (ሶፊያ)',
438 | 'Europe/Stockholm' => 'የመካከለኛው አውሮፓ ሰዓት (ስቶክሆልም)',
439 | 'Europe/Tallinn' => 'የምስራቃዊ አውሮፓ ሰዓት (ታሊን)',
440 | 'Europe/Tirane' => 'የመካከለኛው አውሮፓ ሰዓት (ቴራን)',
441 | 'Europe/Ulyanovsk' => 'የሞስኮ ሰዓት አቆጣጠር (ኡልያኖቭስክ)',
442 | 'Europe/Uzhgorod' => 'የምስራቃዊ አውሮፓ ሰዓት (ኡዝጎሮድ)',
443 | 'Europe/Vaduz' => 'የመካከለኛው አውሮፓ ሰዓት (ቫዱዝ)',
444 | 'Europe/Vatican' => 'የመካከለኛው አውሮፓ ሰዓት (ቫቲካን)',
445 | 'Europe/Vienna' => 'የመካከለኛው አውሮፓ ሰዓት (ቪየና)',
446 | 'Europe/Vilnius' => 'የምስራቃዊ አውሮፓ ሰዓት (ቪሊነስ)',
447 | 'Europe/Volgograd' => 'የቮልጎራድ የሰዓት አቆጣጠር',
448 | 'Europe/Warsaw' => 'የመካከለኛው አውሮፓ ሰዓት (ዋርሶው)',
449 | 'Europe/Zagreb' => 'የመካከለኛው አውሮፓ ሰዓት (ዛግሬብ)',
450 | 'Europe/Zaporozhye' => 'የምስራቃዊ አውሮፓ ሰዓት (ዛፖሮዚይ)',
451 | 'Europe/Zurich' => 'የመካከለኛው አውሮፓ ሰዓት (ዙሪክ)',
452 | 'Indian/Antananarivo' => 'የምስራቅ አፍሪካ ሰዓት (አንታናናሪቮ)',
453 | 'Indian/Chagos' => 'የህንድ ውቅያኖስ ሰዓት (ቻጎስ)',
454 | 'Indian/Christmas' => 'የገና ደሴት ሰዓት',
455 | 'Indian/Cocos' => 'የኮኮስ ደሴቶች ሰዓት',
456 | 'Indian/Comoro' => 'የምስራቅ አፍሪካ ሰዓት (ኮሞሮ)',
457 | 'Indian/Kerguelen' => 'የፈረንሳይ ደቡባዊ እና አንታርክቲክ ሰዓት (ኬርጉለን)',
458 | 'Indian/Mahe' => 'የሴሸልስ ሰዓት (ማሄ)',
459 | 'Indian/Maldives' => 'የማልዲቭስ ሰዓት (ማልዲቨ)',
460 | 'Indian/Mauritius' => 'የማውሪሺየስ ሰዓት (ሞሪሽየስ)',
461 | 'Indian/Mayotte' => 'የምስራቅ አፍሪካ ሰዓት (ማዮቴ)',
462 | 'Indian/Reunion' => 'የሬዩኒየን ሰዓት',
463 | 'MST7MDT' => 'የተራራ የሰዓት አቆጣጠር',
464 | 'PST8PDT' => 'የፓስፊክ ሰዓት አቆጣጠር',
465 | 'Pacific/Apia' => 'የአፒያ ሰዓት (አፒአ)',
466 | 'Pacific/Auckland' => 'የኒው ዚላንድ ሰዓት (ኦክላንድ)',
467 | 'Pacific/Bougainville' => 'የፓፗ ኒው ጊኒ ሰዓት (ቦጌይንቪል)',
468 | 'Pacific/Chatham' => 'የቻታም ሰዓት',
469 | 'Pacific/Easter' => 'የኢስተር ደሴት ሰዓት (ፋሲካ)',
470 | 'Pacific/Efate' => 'የቫኗቱ ሰዓት (ኢፋቴ)',
471 | 'Pacific/Enderbury' => 'የፊኒክስ ደሴቶች ሰዓት (ኢንደርበሪ)',
472 | 'Pacific/Fakaofo' => 'የቶኬላው ሰዓት (ፋካኦፎ)',
473 | 'Pacific/Fiji' => 'የፊጂ ሰዓት',
474 | 'Pacific/Funafuti' => 'የቱቫሉ ሰዓት (ፈናፉቲ)',
475 | 'Pacific/Galapagos' => 'የጋላፓጎስ ሰዓት',
476 | 'Pacific/Gambier' => 'የጋምቢየር ሰዓት',
477 | 'Pacific/Guadalcanal' => 'የሰለሞን ደሴቶች ሰዓት (ጉዋዳልካናል)',
478 | 'Pacific/Guam' => 'የቻሞሮ መደበኛ ሰዓት (ጉአም)',
479 | 'Pacific/Honolulu' => 'የሃዋይ አሌኡት ሰዓት አቆጣጠር (ሆኖሉሉ)',
480 | 'Pacific/Johnston' => 'የሃዋይ አሌኡት ሰዓት አቆጣጠር (ጆንስተን)',
481 | 'Pacific/Kiritimati' => 'የላይን ደሴቶች ሰዓት (ኪሪቲማቲ)',
482 | 'Pacific/Kosrae' => 'የኮስራኤ ሰዓት (ኮስሬ)',
483 | 'Pacific/Kwajalein' => 'የማርሻል ደሴቶች ሰዓት (ክዋጃሊን)',
484 | 'Pacific/Majuro' => 'የማርሻል ደሴቶች ሰዓት (ማጁሩ)',
485 | 'Pacific/Marquesas' => 'የማርኴሳስ ሰዓት (ማርክዌሳስ)',
486 | 'Pacific/Midway' => 'የሳሞዋ ሰዓት (ሚድወይ)',
487 | 'Pacific/Nauru' => 'የናውሩ ሰዓት',
488 | 'Pacific/Niue' => 'የኒዩዌ ሰዓት (ኒዌ)',
489 | 'Pacific/Norfolk' => 'የኖርፎልክ ደሴቶች ሰዓት',
490 | 'Pacific/Noumea' => 'የኒው ካሌዶኒያ ሰዓት (ናኦሚአ)',
491 | 'Pacific/Pago_Pago' => 'የሳሞዋ ሰዓት (ፓጎ ፓጎ)',
492 | 'Pacific/Palau' => 'የፓላው ሰዓት',
493 | 'Pacific/Pitcairn' => 'የፒትካይርን ሰዓት (ፒትከይርን)',
494 | 'Pacific/Ponape' => 'የፖናፔ ሰዓት (ፖህንፔ)',
495 | 'Pacific/Port_Moresby' => 'የፓፗ ኒው ጊኒ ሰዓት (ፖርት ሞሬስባይ)',
496 | 'Pacific/Rarotonga' => 'የኩክ ደሴቶች ሰዓት (ራሮቶንጋ)',
497 | 'Pacific/Saipan' => 'የቻሞሮ መደበኛ ሰዓት (ሴይፓን)',
498 | 'Pacific/Tahiti' => 'የታሂቲ ሰዓት',
499 | 'Pacific/Tarawa' => 'የጂልበርት ደሴቶች ሰዓት (ታራዋ)',
500 | 'Pacific/Tongatapu' => 'የቶንጋ ሰዓት (ቶንጋታፑ)',
501 | 'Pacific/Truk' => 'የቹክ ሰዓት',
502 | 'Pacific/Wake' => 'የዌክ ደሴት ሰዓት (ዋኬ)',
503 | 'Pacific/Wallis' => 'የዋሊስ እና ፉቱና ሰዓት',
504 | ];
505 | }
506 |
--------------------------------------------------------------------------------