mirror of
https://github.com/rlanvin/php-rrule.git
synced 2025-03-14 06:29:16 +01:00
Compare commits
19 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
343c015118 | ||
|
fd213620c2 | ||
|
c68668b195 | ||
|
bef9568de9 | ||
|
cb5c6f44f2 | ||
|
a2dd785693 | ||
|
4b19d8ef60 | ||
|
747bc473d9 | ||
|
0f48c3f93b | ||
|
75b76c85c9 | ||
|
9fd062ae06 | ||
|
44d5b4c3f0 | ||
|
963a466e48 | ||
|
8bbb753c5a | ||
|
949addfb2d | ||
|
7af14b7dac | ||
|
9cd53d7bcc | ||
|
2cad19b61d | ||
|
bef5c05e43 |
2
.github/workflows/tests.yml
vendored
2
.github/workflows/tests.yml
vendored
@ -7,7 +7,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
php: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1']
|
||||
php: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3']
|
||||
name: PHP ${{ matrix.php }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -2,4 +2,5 @@
|
||||
vendor
|
||||
test.php
|
||||
composer.lock
|
||||
.idea
|
||||
.idea
|
||||
.phpunit.result.cache
|
41
CHANGELOG.md
41
CHANGELOG.md
@ -2,6 +2,36 @@
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [2.5.2] - 2025-02-21
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix "november" typo in french translation [#155](https://github.com/rlanvin/php-rrule/issues/155)
|
||||
- Fix incorrect calculation from partially filled cache [#160](https://github.com/rlanvin/php-rrule/issues/160)
|
||||
|
||||
## [2.5.1] - 2024-06-23
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix insufficient type detection for FREQ and WKST leading to deprecation warning in tests with PHP 8.3 [#149](https://github.com/rlanvin/php-rrule/pull/149)
|
||||
- Fix failing tests with ICU 72.1 because of NNBSP
|
||||
- Fix C.UTF8 locale support when intl isn't installed
|
||||
|
||||
## [2.5.0] - 2024-06-08
|
||||
|
||||
### Fixed
|
||||
|
||||
- Swedish: Corrects the spelling of monday and the grammar of enumeration partials. [#134](https://github.com/rlanvin/php-rrule/pull/134)
|
||||
- Spanish: Improve clarity in daily and weekly recurrence translation [#147](https://github.com/rlanvin/php-rrule/pull/147)
|
||||
- Dutch: weekdays and months are written in lowercase [#136](https://github.com/rlanvin/php-rrule/pull/136)
|
||||
- Better handle TZ with Exchange / M365 generated iCal files [#143](https://github.com/rlanvin/php-rrule/pull/143)
|
||||
|
||||
### Added
|
||||
|
||||
- Human readable time of day option [#124](https://github.com/rlanvin/php-rrule/pull/124)
|
||||
- Japanese translation [#139](https://github.com/rlanvin/php-rrule/pull/139)
|
||||
- Czech translation [#137](https://github.com/rlanvin/php-rrule/pull/137)
|
||||
|
||||
## [2.4.1] - 2023-06-07
|
||||
|
||||
### Fixed
|
||||
@ -20,7 +50,7 @@
|
||||
|
||||
### Added
|
||||
|
||||
- Added Portugese translation [#108](https://github.com/rlanvin/php-rrule/pull/108)
|
||||
- Added Portuguese translation [#108](https://github.com/rlanvin/php-rrule/pull/108)
|
||||
- Added Polish translation [#106](https://github.com/rlanvin/php-rrule/pull/106)
|
||||
|
||||
## [2.3.2] - 2022-05-03
|
||||
@ -91,7 +121,7 @@
|
||||
|
||||
## [2.0.0-rc1] - 2019-01-13
|
||||
|
||||
- Rewrite the core algorithm to use a native PHP generator, drop compability with PHP < 5.6 [#43](https://github.com/rlanvin/php-rrule/issues/43)
|
||||
- Rewrite the core algorithm to use a native PHP generator, drop compatibility with PHP < 5.6 [#43](https://github.com/rlanvin/php-rrule/issues/43)
|
||||
|
||||
### Added
|
||||
|
||||
@ -205,7 +235,7 @@
|
||||
|
||||
### Fixed
|
||||
|
||||
- `RRule::parseRfcString()` is strictier and will not accept invalid `DTSTART` and `UNTIL` formats (use the array syntax in the constructor with `DateTime` objects if you need to create rules with complex combinations of timezones). [#13](https://github.com/rlanvin/php-rrule/issues/13)
|
||||
- `RRule::parseRfcString()` is stricter and will not accept invalid `DTSTART` and `UNTIL` formats (use the array syntax in the constructor with `DateTime` objects if you need to create rules with complex combinations of timezones). [#13](https://github.com/rlanvin/php-rrule/issues/13)
|
||||
|
||||
## [1.2.0] - 2016-04-09
|
||||
|
||||
@ -250,7 +280,10 @@
|
||||
|
||||
- First release, everything before that was unversioned (`dev-master` was used).
|
||||
|
||||
[Unreleased]: https://github.com/rlanvin/php-rrule/compare/v2.4.1...HEAD
|
||||
[Unreleased]: https://github.com/rlanvin/php-rrule/compare/v2.5.2...HEAD
|
||||
[2.5.2]: https://github.com/rlanvin/php-rrule/compare/v2.5.1...v2.5.2
|
||||
[2.5.1]: https://github.com/rlanvin/php-rrule/compare/v2.5.0...v2.5.1
|
||||
[2.5.0]: https://github.com/rlanvin/php-rrule/compare/v2.4.1...v2.5.0
|
||||
[2.4.1]: https://github.com/rlanvin/php-rrule/compare/v2.4.0...v2.4.1
|
||||
[2.4.0]: https://github.com/rlanvin/php-rrule/compare/v2.3.2...v2.4.0
|
||||
[2.3.2]: https://github.com/rlanvin/php-rrule/compare/v2.3.1...v2.3.2
|
||||
|
@ -76,7 +76,7 @@ you `lno1wkst`). I tried to comment and explain as much of the algorithm as poss
|
||||
in this PHP port, so feel free to check the code if you're interested.
|
||||
|
||||
The lib differs from the python version in various aspects, notably in the
|
||||
respect of the RFC. This version is a bit strictier and will not accept many
|
||||
respect of the RFC. This version is a bit stricter and will not accept many
|
||||
non-compliant combinations of rule parts, that the python version otherwise accepts.
|
||||
There are also some additional features in this version.
|
||||
|
||||
|
@ -179,7 +179,7 @@ class RRule implements RRuleInterface
|
||||
|
||||
/**
|
||||
* The constructor needs the entire rule at once.
|
||||
* There is no setter after the class has been instanciated,
|
||||
* There is no setter after the class has been instantiated,
|
||||
* because in order to validate some BYXXX parts, we need to know
|
||||
* the value of some other parts (FREQ or other BXXX parts).
|
||||
*
|
||||
@ -219,34 +219,38 @@ class RRule implements RRuleInterface
|
||||
$this->rule = $parts; // save original rule
|
||||
|
||||
// WKST
|
||||
$parts['WKST'] = strtoupper($parts['WKST']);
|
||||
if (! array_key_exists($parts['WKST'], self::WEEKDAYS)) {
|
||||
if (is_string($parts['WKST'])) {
|
||||
$parts['WKST'] = strtoupper($parts['WKST']);
|
||||
if (array_key_exists($parts['WKST'], self::WEEKDAYS)) {
|
||||
$this->wkst = self::WEEKDAYS[$parts['WKST']];
|
||||
}
|
||||
}
|
||||
|
||||
if (!$this->wkst) {
|
||||
throw new \InvalidArgumentException(
|
||||
'The WKST rule part must be one of the following: '
|
||||
.implode(', ',array_keys(self::WEEKDAYS))
|
||||
);
|
||||
}
|
||||
$this->wkst = self::WEEKDAYS[$parts['WKST']];
|
||||
|
||||
// FREQ
|
||||
if (is_integer($parts['FREQ'])) {
|
||||
if ($parts['FREQ'] > self::SECONDLY || $parts['FREQ'] < self::YEARLY) {
|
||||
throw new \InvalidArgumentException(
|
||||
'The FREQ rule part must be one of the following: '
|
||||
.implode(', ',array_keys(self::FREQUENCIES))
|
||||
);
|
||||
if ($parts['FREQ'] <= self::SECONDLY && $parts['FREQ'] >= self::YEARLY) {
|
||||
$this->freq = $parts['FREQ'];
|
||||
}
|
||||
$this->freq = $parts['FREQ'];
|
||||
}
|
||||
else { // string
|
||||
elseif (is_string($parts['FREQ'])) {
|
||||
$parts['FREQ'] = strtoupper($parts['FREQ']);
|
||||
if (! array_key_exists($parts['FREQ'], self::FREQUENCIES)) {
|
||||
throw new \InvalidArgumentException(
|
||||
'The FREQ rule part must be one of the following: '
|
||||
.implode(', ',array_keys(self::FREQUENCIES))
|
||||
);
|
||||
if (array_key_exists($parts['FREQ'], self::FREQUENCIES)) {
|
||||
$this->freq = self::FREQUENCIES[$parts['FREQ']];
|
||||
}
|
||||
$this->freq = self::FREQUENCIES[$parts['FREQ']];
|
||||
}
|
||||
|
||||
if (!$this->freq) {
|
||||
throw new \InvalidArgumentException(
|
||||
'The FREQ rule part must be one of the following: '
|
||||
.implode(', ',array_keys(self::FREQUENCIES))
|
||||
);
|
||||
}
|
||||
|
||||
// INTERVAL
|
||||
@ -558,7 +562,7 @@ class RRule implements RRuleInterface
|
||||
/**
|
||||
* Format a rule according to RFC 5545
|
||||
*
|
||||
* @param bool $include_timezone Wether to generate a rule with timezone identifier on DTSTART (and UNTIL) or not.
|
||||
* @param bool $include_timezone Whether to generate a rule with timezone identifier on DTSTART (and UNTIL) or not.
|
||||
* @return string
|
||||
*/
|
||||
public function rfcString($include_timezone = true)
|
||||
@ -717,7 +721,7 @@ class RRule implements RRuleInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the rrule has no end condition (infite)
|
||||
* Return true if the rrule has no end condition (infinite)
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
@ -822,7 +826,7 @@ class RRule implements RRuleInterface
|
||||
}
|
||||
}
|
||||
|
||||
// so now we have exhausted all the BYXXX rules (exept bysetpos),
|
||||
// so now we have exhausted all the BYXXX rules (except bysetpos),
|
||||
// we still need to consider frequency and interval
|
||||
list($start_year, $start_month) = explode('-',$this->dtstart->format('Y-m'));
|
||||
switch ($this->freq) {
|
||||
@ -984,7 +988,7 @@ class RRule implements RRuleInterface
|
||||
/**
|
||||
* Returns the number of occurrences in this rule. It will have go
|
||||
* through the whole recurrence, if this hasn't been done before, which
|
||||
* introduces a performance penality.
|
||||
* introduces a performance penalty.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
@ -1358,16 +1362,8 @@ class RRule implements RRuleInterface
|
||||
|
||||
if ($occurrence) {
|
||||
$dtstart = clone $occurrence; // since DateTime is not immutable, clone to avoid any problem
|
||||
// so we skip the last occurrence of the cache
|
||||
if ($this->freq === self::SECONDLY) {
|
||||
$dtstart = $dtstart->modify('+'.$this->interval.'second');
|
||||
}
|
||||
else {
|
||||
$dtstart = $dtstart->modify('+1second');
|
||||
}
|
||||
}
|
||||
|
||||
if ($dtstart === null) {
|
||||
elseif ($dtstart === null) {
|
||||
$dtstart = clone $this->dtstart;
|
||||
}
|
||||
|
||||
@ -1408,8 +1404,21 @@ class RRule implements RRuleInterface
|
||||
}
|
||||
}
|
||||
|
||||
// if we restarted the calculation from cache, we know that dtstart has already been yielded
|
||||
// so we can skip ahead to the next second to avoid the same date to be yielded again
|
||||
// we need to do that after the correct frame as been set (see https://github.com/rlanvin/php-rrule/issues/160)
|
||||
if ($occurrence) {
|
||||
if ($this->freq === self::SECONDLY) {
|
||||
$dtstart = $dtstart->modify('+'.$this->interval.'second');
|
||||
}
|
||||
else {
|
||||
$dtstart = $dtstart->modify('+1second');
|
||||
}
|
||||
}
|
||||
|
||||
$max_cycles = self::MAX_CYCLES[$this->freq <= self::DAILY ? $this->freq : self::DAILY];
|
||||
for ($i = 0; $i < $max_cycles; $i++) {
|
||||
|
||||
// 1. get an array of all days in the next interval (day, month, week, etc.)
|
||||
// we filter out from this array all days that do not match the BYXXX conditions
|
||||
// to speed things up, we use days of the year (day numbers) instead of date
|
||||
@ -1542,6 +1551,7 @@ class RRule implements RRuleInterface
|
||||
$this->total = $total;
|
||||
return;
|
||||
}
|
||||
|
||||
$total += 1;
|
||||
$this->cache[] = clone $occurrence;
|
||||
yield clone $occurrence; // yield
|
||||
@ -1572,6 +1582,7 @@ class RRule implements RRuleInterface
|
||||
$this->total = $total;
|
||||
return;
|
||||
}
|
||||
|
||||
$total += 1;
|
||||
$this->cache[] = clone $occurrence;
|
||||
yield clone $occurrence; // yield
|
||||
@ -2068,9 +2079,10 @@ class RRule implements RRuleInterface
|
||||
* | `locale` | string | The locale to use (autodetect)
|
||||
* | `fallback` | string | Fallback locale if main locale is not found (default en)
|
||||
* | `date_formatter` | callable| Function used to format the date (takes date, returns formatted)
|
||||
* | `explicit_inifite`| bool | Mention "forever" if the rule is infinite (true)
|
||||
* | `explicit_infinite`| bool | Mention "forever" if the rule is infinite (true)
|
||||
* | `dtstart` | bool | Mention the start date (true)
|
||||
* | `include_start` | bool |
|
||||
* | `start_time_only` | bool | Mention the time of day only, without the date
|
||||
* | `include_until` | bool |
|
||||
* | `custom_path` | string |
|
||||
*
|
||||
@ -2091,6 +2103,7 @@ class RRule implements RRuleInterface
|
||||
'fallback' => 'en',
|
||||
'explicit_infinite' => true,
|
||||
'include_start' => true,
|
||||
'start_time_only' => false,
|
||||
'include_until' => true,
|
||||
'custom_path' => null
|
||||
);
|
||||
@ -2100,13 +2113,13 @@ class RRule implements RRuleInterface
|
||||
$default_opt['locale'] = \Locale::getDefault();
|
||||
} else {
|
||||
$default_opt['locale'] = setlocale(LC_CTYPE, 0);
|
||||
if ($default_opt['locale'] == 'C') {
|
||||
if (!$default_opt['locale'] || $default_opt['locale'][0] == 'C') {
|
||||
$default_opt['locale'] = 'en';
|
||||
}
|
||||
}
|
||||
|
||||
if ($opt['use_intl']) {
|
||||
$default_opt['date_format'] = \IntlDateFormatter::SHORT;
|
||||
$default_opt['date_format'] = isset($opt['start_time_only']) && $opt['start_time_only'] ? \IntlDateFormatter::NONE : \IntlDateFormatter::SHORT;
|
||||
if ($this->freq >= self::SECONDLY || not_empty($this->rule['BYSECOND'])) {
|
||||
$default_opt['time_format'] = \IntlDateFormatter::LONG;
|
||||
}
|
||||
@ -2114,7 +2127,7 @@ class RRule implements RRuleInterface
|
||||
$default_opt['time_format'] = \IntlDateFormatter::SHORT;
|
||||
}
|
||||
else {
|
||||
$default_opt['time_format'] = \IntlDateFormatter::NONE;
|
||||
$default_opt['time_format'] = isset($opt['start_time_only']) && $opt['start_time_only'] ? \IntlDateFormatter::SHORT : \IntlDateFormatter::NONE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2149,8 +2162,9 @@ class RRule implements RRuleInterface
|
||||
};
|
||||
}
|
||||
else {
|
||||
$opt['date_formatter'] = function($date) {
|
||||
return $date->format('Y-m-d H:i:s');
|
||||
$opt['date_formatter'] = function ($date) use ($opt) {
|
||||
$format = $opt['start_time_only'] ? 'H:i:s' : 'Y-m-d H:i:s';
|
||||
return $date->format($format);
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -2362,7 +2376,12 @@ class RRule implements RRuleInterface
|
||||
|
||||
if ($opt['include_start']) {
|
||||
// from X
|
||||
$parts['start'] = strtr($i18n['dtstart'], array(
|
||||
if ($opt['start_time_only']) {
|
||||
$value = $this->freq >= self::HOURLY ? 'startingtimeofday' : 'timeofday';
|
||||
} else {
|
||||
$value = 'dtstart';
|
||||
}
|
||||
$parts['start'] = strtr($i18n[$value], array(
|
||||
'%{date}' => $opt['date_formatter']($this->dtstart)
|
||||
));
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ interface RRuleInterface extends \ArrayAccess, \Countable, \IteratorAggregate
|
||||
public function getOccurrences($limit = null);
|
||||
|
||||
/**
|
||||
* Return all the ocurrences after a date, before a date, or between two dates.
|
||||
* Return all the occurrences after a date, before a date, or between two dates.
|
||||
*
|
||||
* @param mixed $begin Can be null to return all occurrences before $end
|
||||
* @param mixed $end Can be null to return all occurrences after $begin
|
||||
@ -97,7 +97,7 @@ interface RRuleInterface extends \ArrayAccess, \Countable, \IteratorAggregate
|
||||
public function isFinite();
|
||||
|
||||
/**
|
||||
* Return true if the rrule has no end condition (infite)
|
||||
* Return true if the rrule has no end condition (infinite)
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
|
@ -52,7 +52,7 @@ trait RRuleTrait
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all the ocurrences after a date, before a date, or between two dates.
|
||||
* Return all the occurrences after a date, before a date, or between two dates.
|
||||
*
|
||||
* @param mixed $begin Can be null to return all occurrences before $end
|
||||
* @param mixed $end Can be null to return all occurrences after $begin
|
||||
|
@ -202,7 +202,7 @@ class RSet implements RRuleInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a RDATE (renamed Date for simplicy, since we don't support full RDATE syntax at the moment)
|
||||
* Add a RDATE (renamed Date for simplicity, since we don't support full RDATE syntax at the moment)
|
||||
*
|
||||
* @param mixed $date a valid date representation or a \DateTime object
|
||||
* @return $this
|
||||
@ -382,7 +382,7 @@ class RSet implements RRuleInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the rrule has no end condition (infite)
|
||||
* Return true if the rrule has no end condition (infinite)
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
@ -556,7 +556,7 @@ class RSet implements RRuleInterface
|
||||
/**
|
||||
* Returns the number of recurrences in this set. It will have go
|
||||
* through the whole recurrence, if this hasn't been done before, which
|
||||
* introduces a performance penality.
|
||||
* introduces a performance penalty.
|
||||
* @return int
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
|
@ -64,7 +64,7 @@ class RfcParser
|
||||
/**
|
||||
* Parse both DTSTART and RRULE (and EXRULE).
|
||||
*
|
||||
* It's impossible to accuratly parse a RRULE in isolation (without the DTSTART)
|
||||
* It's impossible to accurately parse a RRULE in isolation (without the DTSTART)
|
||||
* as some tests depends on DTSTART (notably the date format for UNTIL).
|
||||
*
|
||||
* @param string $string The RFC-like string
|
||||
@ -193,7 +193,7 @@ class RfcParser
|
||||
}
|
||||
// this is an invalid rule, however we'll support it since the JS lib is broken
|
||||
// see https://github.com/rlanvin/php-rrule/issues/25
|
||||
trigger_error("This string is not compliant with the RFC (DTSTART cannot be part of RRULE). It is accepted as is for compability reasons only.", E_USER_NOTICE);
|
||||
trigger_error("This string is not compliant with the RFC (DTSTART cannot be part of RRULE). It is accepted as is for compatibility reasons only.", E_USER_NOTICE);
|
||||
}
|
||||
$parts[$key] = $value;
|
||||
}
|
||||
@ -221,7 +221,7 @@ class RfcParser
|
||||
foreach ($property['params'] as $name => $value) {
|
||||
switch (strtoupper($name)) {
|
||||
case 'TZID':
|
||||
$tz = new \DateTimeZone($value);
|
||||
$tz = self::parseTimeZone($value);
|
||||
break;
|
||||
case 'VALUE':
|
||||
switch ($value) {
|
||||
@ -284,7 +284,7 @@ class RfcParser
|
||||
// Ignore optional words
|
||||
break;
|
||||
case 'TZID':
|
||||
$tz = new \DateTimeZone($value);
|
||||
$tz = self::parseTimeZone($value);
|
||||
break;
|
||||
default:
|
||||
throw new \InvalidArgumentException("Unknown property parameter: $name");
|
||||
@ -325,4 +325,4 @@ class RfcParser
|
||||
|
||||
return new \DateTimeZone($tzid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
174
src/i18n/cz.php
Normal file
174
src/i18n/cz.php
Normal file
@ -0,0 +1,174 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Translation file for Czech language.
|
||||
*
|
||||
* Most strings can be an array, with a value as the key. The system will
|
||||
* pick the translation corresponding to the key. The key "else" will be picked
|
||||
* if no matching value is found. This is useful for plurals.
|
||||
*
|
||||
* Licensed under the MIT license.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE file.
|
||||
*
|
||||
* @author Jakub Kluvánek <jakub@kluvanek.dev>
|
||||
* @link https://github.com/rlanvin/php-rrule
|
||||
*/
|
||||
return array(
|
||||
'yearly' => array(
|
||||
'1' => 'ročně',
|
||||
'2' => 'každé %{interval} roky',
|
||||
'3' => 'každé %{interval} roky',
|
||||
'4' => 'každé %{interval} roky',
|
||||
'else' => 'každých %{interval} let'
|
||||
),
|
||||
'monthly' => array(
|
||||
'1' => 'měsíčně',
|
||||
'2' => 'každé %{interval} měsíce',
|
||||
'3' => 'každé %{interval} měsíce',
|
||||
'4' => 'každé %{interval} měsíce',
|
||||
'else' => 'každých %{interval} měsíců'
|
||||
),
|
||||
'weekly' => array(
|
||||
'1' => 'týdně',
|
||||
'2' => 'každé %{interval} týdny',
|
||||
'3' => 'každé %{interval} týdny',
|
||||
'4' => 'každé %{interval} týdny',
|
||||
'else' => 'každých %{interval} týdnů'
|
||||
),
|
||||
'daily' => array(
|
||||
'1' => 'denně',
|
||||
'2' => 'každé %{interval} dny',
|
||||
'3' => 'každé %{interval} dny',
|
||||
'4' => 'každé %{interval} dny',
|
||||
'5' => 'každé %{interval} dny',
|
||||
'else' => 'každých %{interval} dnů'
|
||||
),
|
||||
'hourly' => array(
|
||||
'1' => 'každou hodinu',
|
||||
'2' => 'každé %{interval} hodiny',
|
||||
'3' => 'každé %{interval} hodiny',
|
||||
'4' => 'každé %{interval} hodiny',
|
||||
'else' => 'každých %{interval} hodin'
|
||||
),
|
||||
'minutely' => array(
|
||||
'1' => 'každou minutu',
|
||||
'2' => 'každé %{interval} minuty',
|
||||
'3' => 'každé %{interval} minuty',
|
||||
'4' => 'každé %{interval} minuty',
|
||||
'else' => 'každých %{interval} minut'
|
||||
),
|
||||
'secondly' => array(
|
||||
'1' => 'každou sekundu',
|
||||
'2' => 'každé %{interval} sekundy',
|
||||
'3' => 'každé %{interval} sekundy',
|
||||
'4' => 'každé %{interval} sekundy',
|
||||
'else' => 'každých %{interval} sekund'
|
||||
),
|
||||
'dtstart' => ', počínaje %{date}',
|
||||
'timeofday' => ' v %{date}',
|
||||
'startingtimeofday' => ' začínající v %{date}',
|
||||
'infinite' => ', navždy',
|
||||
'until' => ', do %{date}',
|
||||
'count' => array(
|
||||
'1' => ', jednou',
|
||||
'else' => ', %{count}x'
|
||||
),
|
||||
'and' => 'a ',
|
||||
'x_of_the_y' => array(
|
||||
'yearly' => '%{x} roku', // e.g. the first Monday of the year, or the first day of the year
|
||||
'monthly' => '%{x} měsíce'
|
||||
),
|
||||
'bymonth' => ' v %{months}',
|
||||
'months' => array(
|
||||
1 => 'leden',
|
||||
2 => 'únor',
|
||||
3 => 'březen',
|
||||
4 => 'duben',
|
||||
5 => 'květen',
|
||||
6 => 'červen',
|
||||
7 => 'červenec',
|
||||
8 => 'srpen',
|
||||
9 => 'září',
|
||||
10 => 'říjen',
|
||||
11 => 'listopad',
|
||||
12 => 'prosinec'
|
||||
),
|
||||
'byweekday' => ' v %{weekdays}',
|
||||
'weekdays' => array(
|
||||
1 => 'pondělí',
|
||||
2 => 'úterý',
|
||||
3 => 'středa',
|
||||
4 => 'čtvrtek',
|
||||
5 => 'pátek',
|
||||
6 => 'sobota',
|
||||
7 => 'neděle'
|
||||
),
|
||||
'nth_weekday' => array(
|
||||
'1' => 'první %{weekday}', // e.g. the first Monday
|
||||
'2' => 'druhé %{weekday}',
|
||||
'3' => 'třetí %{weekday}',
|
||||
'else' => '%{n}. %{weekday}'
|
||||
),
|
||||
'-nth_weekday' => array(
|
||||
'-1' => 'poslední %{weekday}', // e.g. the last Monday
|
||||
'-2' => 'předposlední %{weekday}',
|
||||
'else' => '%{n}. od konce %{weekday}'
|
||||
),
|
||||
'byweekno' => array(
|
||||
'1' => ' v týdnu %{weeks}',
|
||||
'else' => ' v týdnech č.%{weeks}'
|
||||
),
|
||||
'nth_weekno' => '%{n}',
|
||||
'bymonthday' => ' ve dnech %{monthdays}',
|
||||
'nth_monthday' => array(
|
||||
'else' => '%{n}.'
|
||||
),
|
||||
'-nth_monthday' => array(
|
||||
'-1' => 'poslední',
|
||||
'-2' => 'předposlední',
|
||||
'else' => '%{n}. od konce'
|
||||
),
|
||||
'byyearday' => array(
|
||||
'1' => ' ve dnu %{yeardays}',
|
||||
'else' => ' ve dnech %{yeardays}'
|
||||
),
|
||||
'nth_yearday' => array(
|
||||
'1' => 'první',
|
||||
'2' => 'druhý',
|
||||
'3' => 'třetí',
|
||||
'else' => '%{n}.'
|
||||
),
|
||||
'-nth_yearday' => array(
|
||||
'-1' => 'poslední',
|
||||
'-2' => 'předposlední',
|
||||
'else' => '%{n}. od konce'
|
||||
),
|
||||
'byhour' => array(
|
||||
'1' => ' v hodině %{hours}',
|
||||
'else' => ' v hodiny %{hours}'
|
||||
),
|
||||
'nth_hour' => '%{n}h',
|
||||
'byminute' => array(
|
||||
'1' => ' v minutu %{minutes}',
|
||||
'else' => ' v minuty %{minutes}'
|
||||
),
|
||||
'nth_minute' => '%{n}',
|
||||
'bysecond' => array(
|
||||
'1' => ' v sekundě %{seconds}',
|
||||
'else' => ' v sekundy %{seconds}'
|
||||
),
|
||||
'nth_second' => '%{n}',
|
||||
'bysetpos' => ', ale pouze %{setpos} instance sady',
|
||||
'nth_setpos' => array(
|
||||
'1' => 'první',
|
||||
'2' => 'druhá',
|
||||
'3' => 'třetí',
|
||||
'else' => ' %{n}.'
|
||||
),
|
||||
'-nth_setpos' => array(
|
||||
'-1' => 'poslední',
|
||||
'-2' => 'předposlední',
|
||||
'else' => '%{n}. od konce'
|
||||
)
|
||||
);
|
@ -44,6 +44,8 @@ return array(
|
||||
'else' => 'Alle %{interval} Sekunden'
|
||||
),
|
||||
'dtstart' => ', ab dem %{date}',
|
||||
'timeofday' => ' um %{date}',
|
||||
'startingtimeofday' => ' ab %{date}',
|
||||
'infinite' => ', für immer',
|
||||
'until' => ', bis zum %{date}',
|
||||
'count' => array(
|
||||
|
@ -46,6 +46,8 @@ return array(
|
||||
'else' => 'every %{interval} seconds'
|
||||
),
|
||||
'dtstart' => ', starting from %{date}',
|
||||
'timeofday' => ' at %{date}',
|
||||
'startingtimeofday' => ' starting at %{date}',
|
||||
'infinite' => ', forever',
|
||||
'until' => ', until %{date}',
|
||||
'count' => array(
|
||||
|
@ -18,12 +18,12 @@ return array(
|
||||
),
|
||||
'weekly' => array(
|
||||
'1' => 'semanal',
|
||||
'2' => 'cualquier otra semana',
|
||||
'2' => 'semana por medio',
|
||||
'else' => 'cada %{interval} semanas' // cada 8 semanas
|
||||
),
|
||||
'daily' => array(
|
||||
'1' => 'diario',
|
||||
'2' => 'cualquier otro día',
|
||||
'2' => 'día por medio',
|
||||
'else' => 'cada %{interval} días' // cada 8 días
|
||||
),
|
||||
'hourly' => array(
|
||||
@ -39,6 +39,8 @@ return array(
|
||||
'else' => 'cada %{interval} segundos'// cada 8 segundos
|
||||
),
|
||||
'dtstart' => ', empezando desde %{date}',
|
||||
'timeofday' => ' a las %{date}',
|
||||
'startingtimeofday' => ' empezando desde %{date}',
|
||||
'infinite' => ', por siempre',
|
||||
'until' => ', hasta %{date}',
|
||||
'count' => array(
|
||||
|
@ -42,6 +42,8 @@ return array(
|
||||
'else' => 'هر %{interval} ثانیه'
|
||||
),
|
||||
'dtstart' => ', از %{date}',
|
||||
'timeofday' => ' از %{date}',
|
||||
'startingtimeofday' => ' از %{date}',
|
||||
'infinite' => ', همیشه',
|
||||
'until' => ', تا %{date}',
|
||||
'count' => array(
|
||||
|
@ -46,6 +46,8 @@ return array(
|
||||
'else' => 'joka %{interval} sekunti'
|
||||
),
|
||||
'dtstart' => ', alkaen %{date}',
|
||||
'timeofday' => ' klo %{date}',
|
||||
'startingtimeofday' => ' alkaen %{date}',
|
||||
'infinite' => ', jatkuvasti',
|
||||
'until' => ', %{date} asti',
|
||||
'count' => array(
|
||||
|
@ -44,6 +44,8 @@ return array(
|
||||
'else' => 'toutes les %{interval} secondes'
|
||||
),
|
||||
'dtstart' => ', à partir du %{date}',
|
||||
'timeofday' => ' à %{date}',
|
||||
'startingtimeofday' => ' à partir du %{date}',
|
||||
'infinite' => ', indéfiniment',
|
||||
'until' => ', jusqu\'au %{date}',
|
||||
'count' => array(
|
||||
@ -67,7 +69,7 @@ return array(
|
||||
8 => 'août',
|
||||
9 => 'septembre',
|
||||
10 => 'octobre',
|
||||
11 => 'november',
|
||||
11 => 'novembre',
|
||||
12 => 'décembre',
|
||||
),
|
||||
'byweekday' => ' le %{weekdays}',
|
||||
|
@ -41,6 +41,8 @@ return array(
|
||||
'else' => 'כל %{interval} שניות'
|
||||
),
|
||||
'dtstart' => ', החל מ%{date}',
|
||||
'timeofday' => ' החל מ%{date}',
|
||||
'startingtimeofday' => ' החל מ%{date}',
|
||||
'infinite' => ', לעד',
|
||||
'until' => ', עד %{date}',
|
||||
'count' => array(
|
||||
|
@ -38,6 +38,8 @@ return array(
|
||||
'else' => 'ogni %{interval} secondi'
|
||||
),
|
||||
'dtstart' => ', a partire dal %{date}',
|
||||
'timeofday' => ' alle %{date}',
|
||||
'startingtimeofday' => ' a partire dal %{date}',
|
||||
'infinite' => ', per sempre',
|
||||
'until' => ', fino al %{date}',
|
||||
'count' => array(
|
||||
|
143
src/i18n/ja.php
Normal file
143
src/i18n/ja.php
Normal file
@ -0,0 +1,143 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Translation file for Japanese language.
|
||||
*
|
||||
* Most strings can be an array, with a value as the key. The system will
|
||||
* pick the translation corresponding to the key. The key "else" will be picked
|
||||
* if no matching value is found. This is useful for plurals.
|
||||
*
|
||||
* Licensed under the MIT license.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE file.
|
||||
*
|
||||
* @author Taichi Kurihara <taichi.kurihara416@gmail.com>
|
||||
* @link https://github.com/Kuri-Tai/php-rrule
|
||||
*/
|
||||
return array(
|
||||
'yearly' => array(
|
||||
'1' => '毎年',
|
||||
'else' => '%{interval} 年ごと',
|
||||
),
|
||||
'monthly' => array(
|
||||
'1' => '毎月',
|
||||
'else' => '%{interval} か月ごと',
|
||||
),
|
||||
'weekly' => array(
|
||||
'1' => '毎週',
|
||||
'2' => '隔週',
|
||||
'else' => '%{interval} 週間ごと',
|
||||
),
|
||||
'daily' => array(
|
||||
'1' => '毎日',
|
||||
'2' => '隔日',
|
||||
'else' => '%{interval} 日ごと',
|
||||
),
|
||||
'hourly' => array(
|
||||
'1' => '毎時',
|
||||
'else' => '%{interval} 時間ごと',
|
||||
),
|
||||
'minutely' => array(
|
||||
'1' => '毎分',
|
||||
'else' => '%{interval} 分ごと',
|
||||
),
|
||||
'secondly' => array(
|
||||
'1' => '毎秒',
|
||||
'else' => '%{interval} 秒ごと',
|
||||
),
|
||||
'dtstart' => ', %{date} から',
|
||||
'infinite' => ', 期日なし',
|
||||
'until' => ', %{date} まで',
|
||||
'count' => array(
|
||||
'1' => ', 1 回',
|
||||
'else' => ', %{count} 回',
|
||||
),
|
||||
'and' => 'かつ ',
|
||||
'x_of_the_y' => array(
|
||||
'yearly' => 'その年の %{x}', // e.g. その年の 最初の 月曜日, もしくは その年の 最初の 日
|
||||
'monthly' => 'その月の %{x}',
|
||||
),
|
||||
'bymonth' => ' %{months}',
|
||||
'months' => array(
|
||||
1 => '1月',
|
||||
2 => '2月',
|
||||
3 => '3月',
|
||||
4 => '4月',
|
||||
5 => '5月',
|
||||
6 => '6月',
|
||||
7 => '7月',
|
||||
8 => '8月',
|
||||
9 => '9月',
|
||||
10 => '10月',
|
||||
11 => '11月',
|
||||
12 => '12月',
|
||||
),
|
||||
'byweekday' => ' %{weekdays}',
|
||||
'weekdays' => array(
|
||||
1 => '月曜日',
|
||||
2 => '火曜日',
|
||||
3 => '水曜日',
|
||||
4 => '木曜日',
|
||||
5 => '金曜日',
|
||||
6 => '土曜日',
|
||||
7 => '日曜日',
|
||||
),
|
||||
'nth_weekday' => array(
|
||||
'1' => '最初の %{weekday}', // e.g. 最初の 月曜日
|
||||
'else' => '%{n}番目の %{weekday}',
|
||||
),
|
||||
'-nth_weekday' => array(
|
||||
'-1' => '最後の %{weekday}', // e.g. 最後の 月曜日
|
||||
'else' => '最後から%{n}番目の %{weekday}',
|
||||
),
|
||||
'byweekno' => array(
|
||||
'1' => ' 第%{weeks}週目',
|
||||
'else' => ' 第%{weeks}週目',
|
||||
),
|
||||
'nth_weekno' => '%{n}',
|
||||
'bymonthday' => ' %{monthdays}',
|
||||
'nth_monthday' => array(
|
||||
'1' => '1番目の',
|
||||
'else' => '%{n}番目の',
|
||||
),
|
||||
'-nth_monthday' => array(
|
||||
'-1' => '最後の',
|
||||
'else' => '最後から%{n}番目の',
|
||||
),
|
||||
'byyearday' => array(
|
||||
'1' => ' %{yeardays}',
|
||||
'else' => ' %{yeardays}',
|
||||
),
|
||||
'nth_yearday' => array(
|
||||
'1' => '1番目の',
|
||||
'else' => '%{n}番目の',
|
||||
),
|
||||
'-nth_yearday' => array(
|
||||
'-1' => '最後の',
|
||||
'else' => '最後から%{n}番目の',
|
||||
),
|
||||
'byhour' => array(
|
||||
'1' => ' %{hours}',
|
||||
'else' => ' %{hours}',
|
||||
),
|
||||
'nth_hour' => '%{n}時',
|
||||
'byminute' => array(
|
||||
'1' => ' %{minutes}',
|
||||
'else' => ' %{minutes}',
|
||||
),
|
||||
'nth_minute' => '%{n}分',
|
||||
'bysecond' => array(
|
||||
'1' => ' %{seconds}',
|
||||
'else' => ' %{seconds}',
|
||||
),
|
||||
'nth_second' => '%{n}秒',
|
||||
'bysetpos' => ', ただし、そのうちの %{setpos} 該当するもののみ',
|
||||
'nth_setpos' => array(
|
||||
'1' => '最初の',
|
||||
'else' => '%{n}番目の',
|
||||
),
|
||||
'-nth_setpos' => array(
|
||||
'-1' => '最後の',
|
||||
'else' => '最後から%{n}番目の',
|
||||
),
|
||||
);
|
@ -46,6 +46,8 @@ return array(
|
||||
'else' => 'elke %{interval} seconden'
|
||||
),
|
||||
'dtstart' => ', wordt gestart vanaf %{date}',
|
||||
'timeofday' => ' om %{date}',
|
||||
'startingtimeofday' => ' wordt gestart vanaf %{date}',
|
||||
'infinite' => ', oneindig',
|
||||
'until' => ', tot en met %{date}',
|
||||
'count' => array(
|
||||
@ -59,28 +61,28 @@ return array(
|
||||
),
|
||||
'bymonth' => ' in %{months}',
|
||||
'months' => array(
|
||||
1 => 'Januari',
|
||||
2 => 'Februari',
|
||||
3 => 'Maart',
|
||||
4 => 'April',
|
||||
5 => 'Mei',
|
||||
6 => 'Juni',
|
||||
7 => 'Juli',
|
||||
8 => 'Augustus',
|
||||
9 => 'September',
|
||||
10 => 'Oktober',
|
||||
11 => 'November',
|
||||
12 => 'December',
|
||||
1 => 'januari',
|
||||
2 => 'februari',
|
||||
3 => 'maart',
|
||||
4 => 'april',
|
||||
5 => 'mei',
|
||||
6 => 'juni',
|
||||
7 => 'juli',
|
||||
8 => 'augustus',
|
||||
9 => 'september',
|
||||
10 => 'oktober',
|
||||
11 => 'november',
|
||||
12 => 'december',
|
||||
),
|
||||
'byweekday' => ' op %{weekdays}',
|
||||
'weekdays' => array(
|
||||
1 => 'Maandag',
|
||||
2 => 'Dinsdag',
|
||||
3 => 'Woensdag',
|
||||
4 => 'Donderdag',
|
||||
5 => 'Vrijdag',
|
||||
6 => 'Zaterdag',
|
||||
7 => 'Zondag',
|
||||
1 => 'maandag',
|
||||
2 => 'dinsdag',
|
||||
3 => 'woensdag',
|
||||
4 => 'donderdag',
|
||||
5 => 'vrijdag',
|
||||
6 => 'zaterdag',
|
||||
7 => 'zondag',
|
||||
),
|
||||
'nth_weekday' => array(
|
||||
'1' => 'de eerste %{weekday}', // e.g. the first Monday
|
||||
|
@ -58,6 +58,8 @@ return array(
|
||||
'else' => 'co %{interval} sekund'
|
||||
),
|
||||
'dtstart' => ', zaczynając od %{date}',
|
||||
'timeofday' => ' o %{date}',
|
||||
'startingtimeofday' => ' zaczynając od %{date}',
|
||||
'infinite' => ', zawsze',
|
||||
'until' => ', do daty %{date}',
|
||||
'count' => array(
|
||||
|
@ -39,6 +39,8 @@ return array(
|
||||
'else' => 'cada %{interval} segundos'// cada 8 segundos
|
||||
),
|
||||
'dtstart' => ', começando de %{date}',
|
||||
'timeofday' => ' às %{date}',
|
||||
'startingtimeofday' => ' começando de %{date}',
|
||||
'infinite' => ', para sempre',
|
||||
'until' => ', até %{date}',
|
||||
'count' => array(
|
||||
|
@ -51,6 +51,8 @@ return array(
|
||||
'else' => 'var %{interval}:e sekund'
|
||||
),
|
||||
'dtstart' => ', börjar %{date}',
|
||||
'timeofday' => ' kl %{date}',
|
||||
'startingtimeofday' => ' börjar %{date}',
|
||||
'infinite' => ', tills vidare',
|
||||
'until' => ', t.om %{date}',
|
||||
'count' => array(
|
||||
@ -79,7 +81,7 @@ return array(
|
||||
),
|
||||
'byweekday' => ' på %{weekdays}',
|
||||
'weekdays' => array(
|
||||
1 => 'Månday',
|
||||
1 => 'Måndag',
|
||||
2 => 'Tisdag',
|
||||
3 => 'Onsdag',
|
||||
4 => 'Torsdag',
|
||||
@ -146,14 +148,14 @@ return array(
|
||||
'nth_second' => '%{n}',
|
||||
'bysetpos' => ', men bara %{setpos} tillfället i serien',
|
||||
'nth_setpos' => array(
|
||||
'1' => 'det första',
|
||||
'2' => 'det andra',
|
||||
'3' => 'det tredje',
|
||||
'else' => 'det %{n}:e'
|
||||
'1' => 'den första',
|
||||
'2' => 'den andra',
|
||||
'3' => 'den tredje',
|
||||
'else' => 'den %{n}:e'
|
||||
),
|
||||
'-nth_setpos' => array(
|
||||
'-1' => 'det sista',
|
||||
'-2' => 'det näst sista',
|
||||
'else' => 'det %{n}:e sista'
|
||||
'-1' => 'den sista',
|
||||
'-2' => 'den näst sista',
|
||||
'else' => 'den %{n}:e sista'
|
||||
)
|
||||
);
|
||||
|
85
tests/RRuleTest.php
Executable file → Normal file
85
tests/RRuleTest.php
Executable file → Normal file
@ -20,8 +20,12 @@ class RRuleTest extends TestCase
|
||||
array(array()),
|
||||
array(array('FOOBAR' => 'DAILY')),
|
||||
|
||||
array(array('FREQ' => 'foobar')),
|
||||
'invalid string freq' => [['FREQ' => 'foobar']],
|
||||
'Invalid integer frequency' => [['FREQ' => 42]],
|
||||
'Array freq' => [['FREQ' => array()]],
|
||||
'null freq' => [['FREQ' => null]],
|
||||
'object freq' => [['FREQ' => new Stdclass()]],
|
||||
|
||||
array(array('FREQ' => 'DAILY', 'INTERVAL' => -1)),
|
||||
array(array('FREQ' => 'DAILY', 'INTERVAL' => 1.5)),
|
||||
array(array('FREQ' => 'DAILY', 'UNTIL' => 'foobar')),
|
||||
@ -87,6 +91,9 @@ class RRuleTest extends TestCase
|
||||
array(array('FREQ' => 'MONTHLY', 'BYSECOND' => 61)),
|
||||
|
||||
'Invalid WKST' => [['FREQ' => 'DAILY', 'WKST' => 'XX']],
|
||||
'Null WKST' => [['FREQ' => 'DAILY', 'WKST' => null]],
|
||||
'Array WKST' => [['FREQ' => 'DAILY', 'WKST' => array()]],
|
||||
'Object WKST' => [['FREQ' => 'DAILY', 'WKST' => new stdClass()]],
|
||||
|
||||
'Invalid DTSTART (invalid date)' => [['FREQ' => 'DAILY', 'DTSTART' => new stdClass()]]
|
||||
);
|
||||
@ -241,15 +248,15 @@ class RRuleTest extends TestCase
|
||||
$this->assertEquals($occurrences, $rule->getOccurrences());
|
||||
$this->assertEquals($occurrences, $rule->getOccurrences(), 'Cached version');
|
||||
foreach ($occurrences as $date) {
|
||||
$this->assertTrue($rule->occursAt($date), $date->format('r').'in cached version');
|
||||
$this->assertTrue($rule->occursAt($date), $date->format('r').' in cached version');
|
||||
}
|
||||
$rule->clearCache();
|
||||
foreach ($occurrences as $date) {
|
||||
$this->assertTrue($rule->occursAt($date), $date->format('r').'in uncached version');
|
||||
$this->assertTrue($rule->occursAt($date), $date->format('r').' in uncached version');
|
||||
}
|
||||
$rule->clearCache();
|
||||
for ($i = 0; $i < count($occurrences); $i++) {
|
||||
$this->assertEquals($rule[$i], $occurrences[$i], 'array access uncached');
|
||||
$this->assertEquals($rule[$i], $occurrences[$i], ' array access uncached');
|
||||
}
|
||||
}
|
||||
|
||||
@ -1828,6 +1835,30 @@ class RRuleTest extends TestCase
|
||||
$this->assertSame('2022-11-06T01:00:00-05:00 CDT 1667714400', $rrule[1]->format('c T U'));
|
||||
}
|
||||
|
||||
public function testResumeFromPartiallyFilledCache()
|
||||
{
|
||||
// https://github.com/rlanvin/php-rrule/issues/160
|
||||
$rrule = new \RRule\RRule([
|
||||
'DTSTART' => new DateTime('2023-03-31 23:59:59.000000'),
|
||||
'FREQ' => 'MONTHLY',
|
||||
'INTERVAL' => '12',
|
||||
'WKST' => 'MO',
|
||||
'COUNT' => 3
|
||||
]);
|
||||
|
||||
// Break on first loop during first iterator use.
|
||||
foreach ($rrule as $occurrence) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Print first 3 occurrences (cache used).
|
||||
$this->assertEquals([
|
||||
date_create('2023-03-31 23:59:59'),
|
||||
date_create('2024-03-31 23:59:59'),
|
||||
date_create('2025-03-31 23:59:59')
|
||||
],$rrule->getOccurrences());
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// GetOccurrences
|
||||
|
||||
@ -2987,7 +3018,7 @@ class RRuleTest extends TestCase
|
||||
array('en_US.utf-8', array('en','en_US'), array('en','en_US')),
|
||||
array('en_US_POSIX', array('en','en_US'), array('en','en_US')),
|
||||
array('sv_SE', array('sv','sv_SE'), array('sv','sv_SE')),
|
||||
// case insentitive
|
||||
// case insensitive
|
||||
array('en_sg', array('en','en_SG'), array('en','en_SG')),
|
||||
array('sv_se', array('sv','sv_SE'), array('sv','sv_SE')),
|
||||
// with a dash
|
||||
@ -3113,7 +3144,7 @@ class RRuleTest extends TestCase
|
||||
/**
|
||||
* Tests that the RRule::i18nLoad() fails as expected on invalid $fallback settings
|
||||
*/
|
||||
public function testI18nLoadFallbackFailsWitoutIntl()
|
||||
public function testI18nLoadFallbackFailsWithoutIntl()
|
||||
{
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
$reflector = new ReflectionClass('RRule\RRule');
|
||||
@ -3204,6 +3235,18 @@ class RRuleTest extends TestCase
|
||||
"daily",
|
||||
"daily"
|
||||
),
|
||||
array(
|
||||
"DTSTART:20170202T161500Z\nRRULE:FREQ=MONTHLY;BYMONTHDAY=2",
|
||||
array('locale' => "en", 'start_time_only' => true, 'explicit_infinite' => false),
|
||||
"monthly on the 2nd of the month at 4:15 PM",
|
||||
"monthly on the 2nd of the month at 16:15:00"
|
||||
),
|
||||
array(
|
||||
"DTSTART:20170202T063000Z\nRRULE:FREQ=HOURLY;INTERVAL=7",
|
||||
array('locale' => "en", 'start_time_only' => true, 'explicit_infinite' => false),
|
||||
"every 7 hours starting at 6:30 AM",
|
||||
"every 7 hours starting at 06:30:00"
|
||||
),
|
||||
array(
|
||||
"RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=+2TU",
|
||||
array('locale' => "en", 'include_start' => false, 'explicit_infinite' => false),
|
||||
@ -3247,14 +3290,38 @@ class RRuleTest extends TestCase
|
||||
/**
|
||||
* @dataProvider humanReadableStrings
|
||||
*/
|
||||
public function testHumanReadable($rrule, $options, $withIntl, $withoutIntl, $dtstart = null)
|
||||
public function testHumanReadableWithoutIntl($rrule, $options, $withIntl, $withoutIntl, $dtstart = null)
|
||||
{
|
||||
if ($dtstart) {
|
||||
$dtstart = new DateTime($dtstart);
|
||||
}
|
||||
$rrule = new RRule($rrule, $dtstart);
|
||||
$expected = extension_loaded('intl') ? $withIntl : $withoutIntl;
|
||||
$this->assertEquals($expected, $rrule->humanReadable($options));
|
||||
$options['use_intl'] = false;
|
||||
$this->assertEquals($withoutIntl, $rrule->humanReadable($options));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider humanReadableStrings
|
||||
*/
|
||||
public function testHumanReadableWithIntl($rrule, $options, $withIntl, $withoutIntl, $dtstart = null)
|
||||
{
|
||||
if (!extension_loaded('intl')) {
|
||||
$this->markTestSkipped('intl not loaded');
|
||||
}
|
||||
|
||||
if ($dtstart) {
|
||||
$dtstart = new DateTime($dtstart);
|
||||
}
|
||||
$rrule = new RRule($rrule, $dtstart);
|
||||
|
||||
// Narrow No-Break Space (NNBSP) was added in ICU72.1 before the meridian
|
||||
// as a workaround we replace unicode 0x202f char with a regular space for backwards compatibility
|
||||
if (version_compare(INTL_ICU_VERSION, '72.1') < 0) {
|
||||
// if you don't see the difference, use an editor that displays unicode
|
||||
$withIntl = str_replace(' ', ' ', $withIntl);
|
||||
}
|
||||
|
||||
$this->assertEquals($withIntl, $rrule->humanReadable($options));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -79,6 +79,9 @@ class RfcParserTest extends TestCase
|
||||
array('EXDATE;TZID=America/New_York:19970714T083000',
|
||||
array(date_create('19970714T083000',new \DateTimeZone('America/New_York')))
|
||||
),
|
||||
array('EXDATE;TZID=W. Europe Standard Time:20230915T222222',
|
||||
array(date_create('20230915T222222',new \DateTimeZone('Europe/Berlin')))
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@ -90,4 +93,4 @@ class RfcParserTest extends TestCase
|
||||
$dates = RfcParser::parseExDate($string);
|
||||
$this->assertEquals($dates, $expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user