Skip to content

Commit

Permalink
Merge pull request #15 from kylekatarnls/custom-holidays
Browse files Browse the repository at this point in the history
Implement #2 advanced settings for setHolidays and addHolidays
  • Loading branch information
kylekatarnls authored Nov 5, 2018
2 parents c12276f + 6071799 commit d32504a
Show file tree
Hide file tree
Showing 3 changed files with 266 additions and 14 deletions.
67 changes: 59 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,17 +109,20 @@ It's how you can set your own holidays lists:
Carbon::setHolidays('us-il', array_merge(
Carbon::getHolidays('us-national'),
array(
function ($year) { // Presidents' Day
// Presidents' Day
'presidents-day' => function ($year) {
$date = new DateTime("third monday of february $year");

return $date->format('d/m');
},
function ($year) { // Columbus Day
// Columbus Day
'columbus-day' => function ($year) {
$date = new DateTime("second monday of october $year");

return $date->format('d/m');
},
function ($year) { // Day after Thanksgiving
// Day after Thanksgiving
'thanksgiving-next-day' => function ($year) {
$date = new DateTime("fourth thursday of november $year +1 day");

return $date->format('d/m');
Expand All @@ -129,31 +132,49 @@ Carbon::setHolidays('us-il', array_merge(
Carbon::setHolidays('my-enterprise', array_merge(
Carbon::getHolidays('us-is'),
array(
'12/02', // Lincoln's Birthday
// Lincoln's Birthday
'lincolns-birthday' => '12/02',
)
));
// Then when you select my-enterprise, all us-national,
// us-il and my-enterprise days are enabled
Carbon::setHolidaysRegion('my-enterprise');
```

You can also pass deep array to `setHolidays` to set in the same call holidays dates and either observed flags, names
(in different languages) or both:
```php
Carbon::setHolidays('my-enterprise', array(
'lincolns-birthday' => array(
'date' => '12/02',
'observed' => true,
'name' => array(
'en' => "Lincoln's Birthday",
'fr' => 'Anniversaire du Président Lincoln',
),
),
));
```

#### addHolidays

While setHolidays replace the whole holidays list for a given region, addHolidays
append holidays to the current list.

```php
Carbon::addHolidays('my-list', array(
'20/01',
'21/01',
'poney' => '20/01',
'swimmingpool' => '21/01',
)));
Carbon::addHolidays('my-list', array(
'10/02',
'11/02',
'boss-birthday' => '10/02',
'boss-birthday-next-day' => '11/02',
)));
Carbon::getHolidays('my-list') // contains 20/01, 21/01, 10/02 and 11/02
```

As for `setHolidays`, `addHolidays` handle deep arrays using date, observed and name keys.

#### resetHolidays

Reset all holidays and region previously set.
Expand Down Expand Up @@ -189,6 +210,36 @@ if ($nextWeekHoliday === 'easter' or $nextWeekHoliday === 'christmas') {
}
```

#### getHolidayName

Returns the name of the holiday in the current locale (or English by default) or false if the day is not a holiday.

```php
Carbon::setHolidaysRegion('fr-national');
Carbon::parse('2018-12-25')->getHolidayName() // "Christmas"
Carbon::parse('2018-12-25')->getHolidayName('fr') // "Noël"

Carbon::setLocale('nl');
Carbon::parse('2018-01-15')->getHolidayName() // "Eerste Kerstdag"

// If the name is not translated in business-day
Carbon::setLocale('de');
Carbon::parse('2018-01-15')->getHolidayName() // "Christmas"

// With Carbon 2, you can use local locale:
Carbon::parse('2018-01-15')->locale('sl')->getHolidayName() // "Božič"
```

#### setHolidayName

Wanna rename a holiday name in a particular language? No problem:

```php
Carbon::parse('2018-12-25')->getHolidayName() // "Christmas"
Carbon::setHolidayName('christmas', 'en', 'Christmas Day');
Carbon::parse('2018-12-25')->getHolidayName() // "Christmas Day"
```

#### isBusinessDay

Returns `true` if the date (Carbon instance) is nor a week-end day neither
Expand Down
150 changes: 144 additions & 6 deletions src/Cmixin/BusinessDay/HolidaysList.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ public function setHolidays()
$mixin = $this;

return function ($region, $holidays) use ($mixin) {
$mixin->holidays[$region] = $holidays;
$addHolidays = $mixin->addHolidays();
$mixin->holidays[$region] = array();
$addHolidays($region, $holidays);
};
}

Expand Down Expand Up @@ -93,9 +95,6 @@ public function initializeHolidaysRegion($region = null)
if (!isset($this->holidays[$region])) {
$this->holidays[$region] = array();
}
if ($this->holidays[$region] instanceof \Traversable) {
$this->holidays[$region] = iterator_to_array($this->holidays[$region]);
}

return $this;
}
Expand All @@ -105,6 +104,140 @@ public function initializeHolidaysRegion($region = null)
};
}

/**
* Push a holiday to the holidays list of a region.
*
* @return \Closure
*/
public function pushHoliday()
{
$mixin = $this;

return function ($region, $holiday, $key = null) use ($mixin) {
$mixin->initializeHolidaysRegion($region);

if (is_string($key)) {
$mixin->holidays[$region][$key] = $holiday;

return isset($this) ? $this : null;
}

$mixin->holidays[$region][] = $holiday;

return isset($this) ? $this : null;
};
}

/**
* Set the name(s) of a holiday.
*
* @return \Closure
*/
public function setHolidayName()
{
$mixin = $this;

return function ($holidayKey = null, $name = null, $value = null) use ($mixin) {
static $dictionary;

if (($name = is_string($name) ? array($name => $value) : $name) && $mixin instanceof Holiday) {
if (!isset($dictionary)) {
$dictionary = $mixin->getHolidayNamesDictionary();
}
foreach ($name as $language => $text) {
$dictionary($language);
$mixin->holidayNames[$language][$holidayKey] = $text;
}
}

return isset($this) ? $this : null;
};
}

/**
* Add a holiday to the holidays list of a region then init name and observed state.
*
* @return \Closure
*/
public function addHoliday()
{
$mixin = $this;
$dictionary = $this->setHolidayName();

return function ($region, $holiday, $key = null, $name = null, $observed = null) use ($mixin, $dictionary) {
static $observer;

$mixin->initializeHolidaysRegion($region);
$push = $mixin->pushHoliday();
$push($region, $holiday, $key);

$dictionary($key, $name);

if (isset($observed) && $mixin instanceof HolidayObserver) {
if (!isset($observer)) {
$observer = $mixin->setHolidayObserveStatus();
}
$observer($key, $observed);
}

return isset($this) ? $this : null;
};
}

/**
* Unpack a holiday array definition.
*
* @return \Closure
*/
public function unpackHoliday()
{
return function (&$holiday, &$name = null, &$observed = null) {
if (!isset($holiday['date'])) {
throw new \InvalidArgumentException(
'Holiday array definition should at least contains a "date" entry.'
);
}

if (isset($holiday['name'])) {
$name = $holiday['name'];
}

if (isset($holiday['observed'])) {
$observed = $holiday['observed'];
}

$holiday = $holiday['date'];

return $holiday;
};
}

/**
* Check a holiday definition and unpack it if it's an array.
*
* @return \Closure
*/
public function checkHoliday()
{
$mixin = $this;

return function (&$holiday, $key, &$name = null, &$observed = null) use ($mixin) {
$unpack = $mixin->unpackHoliday();

if (is_array($holiday)) {
if (is_int($key)) {
throw new \InvalidArgumentException(
'Holiday array definition need a string identifier as main array key.'
);
}

$unpack($holiday, $name, $observed);
}

return $holiday;
};
}

/**
* Add holidays to the holidays list.
*
Expand All @@ -116,9 +249,14 @@ public function addHolidays()

return function ($region, $holidays) use ($mixin) {
$mixin->initializeHolidaysRegion($region);
$add = $mixin->addHoliday();
$check = $mixin->checkHoliday();

foreach ($holidays as $holiday) {
$mixin->holidays[$region][] = $holiday;
foreach ($holidays as $key => $holiday) {
$name = null;
$observed = null;
$check($holiday, $key, $name, $observed);
$add($region, $holiday, $key, $name, $observed);
}
};
}
Expand Down
63 changes: 63 additions & 0 deletions tests/Cmixin/BusinessDayTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,69 @@ public function testIsHoliday()
}
}

/**
* @expectedException \InvalidArgumentException
* @expectedExceptionMessage Holiday array definition should at least contains a "date" entry.
*/
public function testAddHolidaysArrayNotDate()
{
$carbon = static::CARBON_CLASS;
$carbon::addHolidays('fr-national', array(
'foo-bar' => array(
'observe' => true,
),
));
}

/**
* @expectedException \InvalidArgumentException
* @expectedExceptionMessage Holiday array definition need a string identifier as main array key.
*/
public function testAddHolidaysArrayIntKey()
{
$carbon = static::CARBON_CLASS;
$carbon::addHolidays('fr-national', array(
array(
'date' => '15/11',
'observe' => true,
),
));
}

public function testAddHolidaysArray()
{
$carbon = static::CARBON_CLASS;
$carbon::addHolidays('fr-national', array(
'foo-bar' => array(
'date' => '15/11',
'observed' => true,
'name' => array(
'en' => 'Foo bar',
'fr' => 'Machin chose',
),
),
));
self::assertFalse($carbon::parse('2010-11-15 03:30:40')->isHoliday());
self::assertFalse($carbon::parse('2010-11-15 03:30:40')->isObservedHoliday());
self::assertFalse($carbon::parse('2010-11-15 03:30:40')->getHolidayName());
$carbon::setHolidaysRegion('fr-national');
self::assertTrue($carbon::parse('2010-11-15 03:30:40')->isHoliday());
self::assertTrue($carbon::parse('2010-11-15 03:30:40')->isObservedHoliday());
self::assertSame('Foo bar', $carbon::parse('2010-11-15 03:30:40')->getHolidayName());
self::assertSame('Machin chose', $carbon::parse('2010-11-15 03:30:40')->getHolidayName('fr'));
self::assertSame('Unknown', $carbon::parse('2010-11-15 03:30:40')->getHolidayName('nl'));
}

public function testSetHolidayName()
{
$carbon = static::CARBON_CLASS;
$carbon::setHolidaysRegion('fr-national');
self::assertSame('Christmas', $carbon::parse('2018-12-25')->getHolidayName());
$carbon::setHolidayName('christmas', 'en', 'Christmas Day');
self::assertSame('Christmas Day', $carbon::parse('2018-12-25')->getHolidayName());
self::assertSame('Noël', $carbon::parse('2018-12-25')->getHolidayName('fr'));
}

public function testIsHolidayStatic()
{
$carbon = static::CARBON_CLASS;
Expand Down

0 comments on commit d32504a

Please sign in to comment.