andegna/日历

如果您想将埃塞俄比亚日历转换为任何其他日历系统(如公历),这就是您需要的正确包。顺便说一句,它还支持阿姆哈拉日期格式以及更多。

v2.4.0 2023-07-21 00:42 UTC

This package is auto-updated.

Last update: 2024-09-21 03:13:51 UTC


README

Build Status StyleCI Scrutinizer Code Quality Code Coverage Total Downloads Latest Stable Version Latest Unstable Version License FOSSA Status

SymfonyInsight

如果您想将 埃塞俄比亚日历 转换为任何其他日历系统(如公历),这就是您需要的(经过良好测试、设计精良、质量高的)包。

顺便说一句,它还支持阿姆哈拉日期格式以及更多。

基本用法 🔨

仅为您提供此包的10,000英尺视图(:airplane:)。

// create a gregorian date using PHP's built-in DateTime class
$gregorian = new DateTime('next monday');

// just pass it to Andegna\DateTime constractor and you will get $ethiopian date
$ethipic = new Andegna\DateTime($gregorian);

格式化它

// format it
// ሰኞ፣ ግንቦት ፯ ቀን (ሥላሴ) 00:00:00 እኩለ፡ሌሊት EAT ፳፻፱ (ማርቆስ) ዓ/ም
echo $ethipic->format(Andegna\Constants::DATE_GEEZ_ORTHODOX);

// ሰኞ፣ ግንቦት 07 ቀን 00:00:00 እኩለ፡ሌሊት EAT 2009 ዓ/ም
echo $ethipic->format(Andegna\Constants::DATE_ETHIOPIAN);

修改它

$ethipic->modify('+8 hours');
$ethipic->sub(new DateInterval('PT30M')); // 30 minutes

// ሰኞ, 07-ግን-2009 07:30:00 EAT
echo $ethipic->format(DATE_COOKIE);

得到您想要的 😉

echo $ethipic->getYear();   // 2009
echo $ethipic->getMonth();  // 9
echo $ethipic->getDay();    // 7

echo $ethipic->getTimestamp(); // 1494822600

// turn it back to gregorian 
// Monday, 15-May-2017 07:30:00 EAT
echo $ethipic->toGregorian()->format(DATE_COOKIE);

要求

Andegna 日历需要 php: >=7.0 和火焰与鲜血 🔥 🐉。

请注意,此包的名称为 andegna/calender 而不是 andegna/calendar。这是一个拼写错误,我没有打算修复。

安装

Andegna 日历 使用 Composer 来管理其依赖项。因此,在使用之前,请确保您已经在您的计算机上安装了Composer。

Composer 是一个用于PHP依赖项管理的工具。它允许您声明项目依赖的库,并且它会为您管理(安装/更新)它们。

如果您以前从未使用过composer 😳,请在再次编写任何PHP代码之前,请务必阅读这里的一些简介

composer require andegna/calender

转换

在我们谈论日历转换之前,我们最好了解一下 Andegna\DateTime 类是如何在内部工作的。

Andegna\DateTime 类只是PHP内置的 DateTime 对象的一个包装,并实现了PHP的 DateTimeInterface(OK!我在一部分上撒了谎,但请相信我,您不需要知道那个 😄)。

所以 Andegna\DateTime 保留着公历日期,并覆盖了 formatgetTimestampadd、'diff' 以及此类方法,以为您提供埃塞俄比亚日历等效值。

这就是它的基本工作原理。

从埃塞俄比亚日期

您可以从给定的埃塞俄比亚日期创建一个 Andegna\DateTime

让我们“创建”

$millennium = Andegna\DateTimeFactory::of(2000, 1, 1);

// ረቡዕ፣ መስከረም 01 ቀን (ልደታ) 00:00:00 እኩለ፡ሌሊት EAT 2000 (ማቴዎስ) ዓ/ም
echo $millennium->format(\Andegna\Constants::DATE_ETHIOPIAN_ORTHODOX).PHP_EOL;

// Wednesday, 12-Sep-2007 00:00:00 EAT
echo $millennium->toGregorian()->format(DATE_COOKIE).PHP_EOL;

$fall_of_derg = Andegna\DateTimeFactory::of(1983, 9, 20, 7, 43, 21, new DateTimeZone('Africa/Addis_Ababa'));

// ማክሰኞ፣ ግንቦት 20 ቀን (ሕንፅተ) 07:43:21 ጡዋት EAT 1983 (ዮሐንስ) ዓ/ም
echo $fall_of_derg->format(\Andegna\Constants::DATE_ETHIOPIAN_ORTHODOX).PHP_EOL;

// Tuesday, 28-May-1991 07:43:21 EAT
echo $fall_of_derg->toGregorian()->format(DATE_COOKIE).PHP_EOL;

从时间戳

假设您有一个来自同一地方的时间戳,可能是来自 time() 函数或某些类型的数据库。

您可以通过这种方式获取 Andegna\DateTime 对象

$timestamp = time(); // or some other place ¯\_(ツ)_/¯

$ethipic = Andegna\DateTimeFactory::fromTimestamp($timestamp);

完成啦。你也可以传递一个DateTimeZone对象

$sheger = new DateTimeZone('Africa/Addis_Ababa');

$ethiopic = Andegna\DateTimeFactory::fromTimestamp($timestamp, $sheger);

从DateTime对象

如果你已经有了DateTime对象,直接给我就好😄

$gregorian = new DateTime('Thu, 11 May 2017 19:01:26 GMT');
$ethiopic = Andegna\DateTimeFactory::fromDateTime($gregorian);

// or just pass it through the constractor
$ethiopic = new Andegna\DateTime(new DateTime('next sunday'));

从日期字符串

这实际上不是这个包的一部分,但可能有人遇到困难。

一般归结为两个选项。你知道日期字符串的格式吗?

如果你知道日期的格式(你很可能知道)你可以创建一个这样的格里历DateTime

// passing the format followed by the date string you got
$gregorian1 = DateTime::createFromFormat('j-M-Y', '15-Feb-2009');
$gregorian2 = DateTime::createFromFormat('m-j-Y', '12-31-1999');
$gregorian3 = DateTime::createFromFormat('Y-m-d H:i:s', '2009-02-15 15:16:17');

要找出格式,请查看这个链接或搜索“PHP日期函数”。

但如果你不知道格式,或者不想弄清楚,只需尝试将其传递给DateTime构造函数。它“可能”会找出日期字符串的格式

$gregorian1 = new DateTime('next sunday');
$gregorian2 = new DateTime('yesterday');
$gregorian3 = new DateTime('1999-12-31');
$gregorian4 = new DateTime('2123-12-31 12:34:56');

$gregorian_bad = new DateTime('12-31-1999'); // this one probably fails

从系统时间

显然你可以这样做

$gregorian = new DateTime('now');
$ethiopic = Andegna\DateTimeFactory::fromDateTime($gregorian);

// but we provided some shortcuts
$now1 = \Andegna\DateTimeFactory::now();
$now2 = new DateTime();

// if you wanna specify time zone
$sheger = new DateTimeZone('Africa/Addis_Ababa');
$now3 = \Andegna\DateTimeFactory::now($sheger);

到DateTime

如果你想得到内部DateTime对象(也就是转换成格里历)。

// create some Ethiopian date how ever you want
$ethiopian_date = \Andegna\DateTimeFactory::now();

// you get a PHP DateTime object to play with
$gregorian = $now->toGregorian();

警告:返回的DateTime对象只是一个克隆。因此,对返回对象的更改/修改不会影响埃塞俄比亚日期。

低级转换

如果你像我一样是个极客,你可能对日历很感兴趣,因为它包含天文学、数学和历史。

PHP日历转换的工作原理

日历扩展提供了一系列函数,用于简化不同日历格式之间的转换(除了埃塞俄比亚)。它基于的中间标准是儒略日计数。儒略日计数是从公元前4713年1月1日起的天数计数。要在日历系统之间进行转换,你必须首先将其转换为儒略日计数,然后转换为所需的日历系统。儒略日计数与儒略历有很大不同!有关儒略日计数的更多信息,请访问」http://www.hermetic.ch/cal_stud/jdn.htm。有关日历系统的更多信息,请访问」http://www.fourmilab.ch/documents/calendar/。本页的摘录包含在这些说明中,并引用在引号中。

这些话直接来自php文档

因此,我们需要实现两个东西来将埃塞俄比亚日期转换为任何其他日期。

  1. 将埃塞俄比亚日期转换为儒略日计数
  2. 将儒略日计数转换为埃塞俄比亚日期

如果你想知道算法,请查看这个链接

或者查看我在GitHub上的gist这个链接

从JDN

use Andegna\Converter\FromJdnConverter;

$jdn = 2457886;
$converter = new FromJdnConverter($jdn);

$day = $converter->getDay();     // 4
$month = $converter->getMonth(); // 9
$year = $converter->getYear();   // 2009

到JDN

use Andegna\Converter\ToJdnConverter;

$converter = new ToJdnConverter(21,3,1986);
echo $jdn = $converter->getJdn();  // 2449322

实际例子

现在,有了这些实用的工具,我们可以将埃塞俄比亚日期转换为任何其他日期。

例如,让我们将其转换为犹太历

$et = new Andegna\DateTime();

// ዓርብ, 04-ግን-2009 14:41:00 EAT
echo $et->format(DATE_COOKIE);

// create a Ethiopian Date `ToJdnConverter`
$converter = new Andegna\Converter\ToJdnConverter($et->getDay(), $et->getMonth(), $et->getYear());

// convert it to jdn
$jdn = $converter->getJdn();

// use the built-in php function to convert the jdn to the jewish calendar 
$jewish_date1 = jdtojewish($jdn);

// 9/16/5777
echo $jewish_date1;

// it also support formating for the return string
$jewish_date2 = jdtojewish($jdn, true,     CAL_JEWISH_ADD_ALAFIM_GERESH);

// convert the return string to utf-8
$jewish_date2 = iconv ('WINDOWS-1255', 'UTF-8', $jewish_date2); 

// טז אייר ה'תשעז
echo $jewish_date2;

例如,让我们将儒略历转换为埃塞俄比亚历

$day = 29;
$month = 4;
$year = 2017;

// get the jdn using the built in php function
$jdn = juliantojd($month, $day, $year);

// convert the jd to Ethiopian Date
$converter = new Andegna\Converter\FromJdnConverter($jdn);

// create a `Andegna\DateTime` from the converted date
$ethiopic = Andegna\DateTimeFactory::fromConverter($converter);

// ዓርብ, 04-ግን-2009 00:00:00 EAT
echo $ethiopic->format(DATE_COOKIE);

// Friday, 12-May-2017 00:00:00 EAT
echo $ethiopic->toGregorian()->format(DATE_COOKIE);

PHP内置支持的日历列表

  • 法国共和国历
  • 格里历
  • 犹太历
  • 儒略历
  • Unix(我知道你在想什么。它不是一个日历,但它很方便)

点击这里了解更多关于这些日历功能

操作

警告

DateTime处理器在内部格里历DateTime上工作。操作月份和年份可能得到预期的结果。

操作内部日期时间

如果你还不了解的话,你可能需要阅读关于DateTimeInterval的内容。

为了给您一个简要概述,DateInterval实现了ISO 8601持续时间。

持续时间是时间间隔的组成部分,定义了时间间隔中经过的时间量。持续时间以P[n]Y[n]M[n]DT[n]H[n]M[n]SP[n]W的格式表示。

在这些表示中,[n]被替换为[n]之后每个日期和时间元素的值。

不需要前面的零。大写字母P、Y、M、W、D、T、H、M和S是每个日期和时间元素的标识符,不会被替换。

  • P是持续时间标识符(对于期间),位于持续时间表示的开始处。
  • Y是年份标识符,位于年数的值之后。
  • M是月份标识符,位于月数的值之后。
  • W是周标识符,位于周数的值之后。
  • D是日标识符,位于日数的值之后。
  • T是时间标识符,位于表示的时间组件之前。
  • H是小时标识符,位于小时数的值之后。
  • M是分钟标识符,位于分钟数的值之后。
  • S是秒标识符,位于秒数的值之后。

例如,"P3Y6M4DT12H30M5S"表示一个持续时间为“三年,六个月,四天,十二小时,三十分钟和五秒”。

// let's start from today
$today = new Andegna\DateTime();

// Adds an amount of days, months, years, hours, minutes and seconds to a DateTime object
$tomorrow = $today->add(new DateInterval('P1D'));
$after_some_days = $today->add(new DateInterval('P10DT4H'));
$after_6_hours = $today->add(new DateInterval('PT6H'));

// Subtracts an amount of days, months, years, hours, minutes and seconds from a DateTime object
$yesterday = $today->sub(new DateInterval('P1D'));
$before_some_days = $today->sub(new DateInterval('P10DT4H'));
$before_6_hours = $today->sub(new DateInterval('PT6H'));

// Alters the DateTime object
$tomorrow = $today->modify('+1 day');
$yesterday = $today->modify('-1 day');
$after_30_minutes = $today->modify('+30 minutes');
$after_30_minutes = $today->modify('next sunday');

如果你想要获取日期之间的差异

$today = new Andegna\DateTime();
$tomorrow = (new Andegna\DateTime())->add(new DateInterval('P1DT2M3S'));

$diff = $today->diff($tomorrow); // returns a DateTimeInterval
var_dump($diff);

将输出类似以下的内容

object(DateInterval)[9]
  ...
  public 'd' => int 1
  public 'h' => int 0
  public 'i' => int 2
  public 's' => int 3
  ...

格式化

介绍

PHP内置的DateTime类有一个用于格式化日期的format方法。

在这里了解格式化方法(点击此处)

在这里阅读格式字符(点击此处)

如果你已经阅读过或者了解PHP日期函数的工作方式,你就已经知道格式化是如何工作的了。

$now = new Andegna\DateTime();

// Let's play a game. It's called "Spot the difference"
echo $now->format(DATE_COOKIE);                   // ዓርብ, 04-ግን-2009 02:09:52 EAT
echo $now->toGregorian()->format(DATE_COOKIE);    // Friday, 12-May-2017 02:09:52 EAT

echo $now->format(DATE_ATOM);                      // 2009-09-04EAT02:09:52+03:00
echo $now->toGregorian()->format(DATE_ATOM);     // 2017-05-12T02:09:52+03:00

echo $now->format('F j ቀን Y');                    // ግንቦት 4 ቀን 2009
echo $now->toGregorian()->format('F j ቀን Y');     // May 12 ቀን 2017

echo $now->format('H:i:s A');                   // 10:09:17 ረፋድ
echo $now->toGregorian()->format('H:i:s A');    // 10:09:17 AM

附加字符格式

常量

我们已经定义了一些方便的常量,按照埃塞俄比亚的惯例来打印 ❤️。

$date = new Andegna\DateTime();

// ዓርብ፣ ግንቦት 04 ቀን 02:35:45 ውደቀት EAT 2009 ዓ/ም
echo $date->format(Andegna\Constants::DATE_ETHIOPIAN);

$date->modify('+8 hours');

// ዓርብ፣ ግንቦት 04 ቀን (ዮሐንስ) 10:35:45 ረፋድ EAT 2009 (ማርቆስ) ዓ/ም
echo $date->format(Andegna\Constants::DATE_ETHIOPIAN_ORTHODOX);

$date->modify('+1 year');

// ቅዳሜ፣ ግንቦት ፬ ቀን 10:35:45 ረፋድ EAT ፳፻፲ ዓ/ም
echo $date->format(Andegna\Constants::DATE_GEEZ);

$date->modify('-3 years')->modify('+1 day');

// ረቡዕ፣ ግንቦት ፭ ቀን (አቦ) 10:35:45 ረፋድ EAT ፳፻፯ (ዮሐንስ) ዓ/ም
echo $date->format(Andegna\Constants::DATE_GEEZ_ORTHODOX);

正如你所看到的3D,这些常量都是以DATE_开头,后面跟着ETHIOPIANGEEZ

后面跟着GEEZ的将返回以古埃塞俄比亚语表示的日期和年份,而ETHIOPIAN将输出我们埃塞俄比亚人常用的ASCII数字。

最后,如果你追加_ORTHODOX,你将得到正教日名称和正教年名称。

假日

复活节

计算复活节日期就像射击一个移动的目标。每个人都认为计算复活节日期是不可能的,有些人认为只有深度信仰的人才可能做到,有些人则认为这是由教会决定的。但是计算复活节日期(也称为Computus)并没有那么复杂。

在最简单的情况下,复活节是北半球春分月后的第一个满月之后的第一个星期日。

这听起来很复杂,在古代很难,但在21世纪却不是这样。

如果您想了解它是如何计算的,我将在即将到来的博客上发布。您可以在此期间阅读这个

让我们看看您如何可以获取特定年份的复活节日期

$easter = new Andegna\Holiday\Easter();

// እሑድ፣ ሚያዝያ 08 ቀን 00:00:00 እኩለ፡ሌሊት EAT 2009 ዓ/ም
echo $easter->get(2009)->format(Andegna\Constants::DATE_ETHIOPIAN).PHP_EOL;

// or just ...
foreach ([2006,2007,2008,2009,2010,2011,2012] as $year) {
    echo $easter->get($year)->format(Andegna\Constants::DATE_ETHIOPIAN).PHP_EOL;
}

将输出

እሑድ፣ ሚያዝያ 12 ቀን 00:00:00 እኩለ፡ሌሊት EAT 2006 ዓ/ም
እሑድ፣ ሚያዝያ 04 ቀን 00:00:00 እኩለ፡ሌሊት EAT 2007 ዓ/ም
እሑድ፣ ሚያዝያ 23 ቀን 00:00:00 እኩለ፡ሌሊት EAT 2008 ዓ/ም
እሑድ፣ ሚያዝያ 08 ቀን 00:00:00 እኩለ፡ሌሊት EAT 2009 ዓ/ም
እሑድ፣ መጋቢት 30 ቀን 00:00:00 እኩለ፡ሌሊት EAT 2010 ዓ/ም
እሑድ፣ ሚያዝያ 20 ቀን 00:00:00 እኩለ፡ሌሊት EAT 2011 ዓ/ም
እሑድ፣ ሚያዝያ 11 ቀን 00:00:00 እኩለ፡ሌሊት EAT 2012 ዓ/ም

验证器

验证。你可能也需要。

为了检查埃塞俄比亚日期(给定 daymonthyear)是否有效,你需要做以下这些

  • 检查 day 是否在 130(包括)之间
  • 检查 month 是否在 113(包括)之间
  • 如果 month13,则检查 day 是否在 16(包括)之间
  • 如果 month13 并且 day6,则检查年份是否为闰年

或者您可以使用我们的验证器

DateValidator

use Andegna\Validator\DateValidator;

// true
$is_valid1 = (new DateValidator(15,9, 2009))->isValid();

// false
$is_valid2 = (new DateValidator(6,13, 2009))->isValid();

LeapYearValidator

use Andegna\Validator\LeapYearValidator;

// false
$is_valid3 = (new LeapYearValidator(2009))->isValid();

// true
$is_valid4 = (new LeapYearValidator(2007))->isValid();

贡献

Fork it
Create your feature branch (git checkout -b my-new-feature)
Commit your changes (git commit -am 'Add some feature')
Push to the branch (git push origin my-new-feature)
Create new Pull Request

许可

FOSSA Status