diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f8e9b9..5944517 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ From Hacktoberfest: - Test coverage at 100% - Arr::isEmpty() methods thanks to @Tautve for the implementation and @RoadSigns for the review - Allow Arr::flatMap() to support multidimensional arrays by @RoadSigns +- Add toLocaleString() to get the string representation of the elements in the array ## 0.0.9 - 2022-10-02 From Hacktoberfest: diff --git a/doc/arr.md b/doc/arr.md index 54059a9..cc19350 100644 --- a/doc/arr.md +++ b/doc/arr.md @@ -384,3 +384,23 @@ var_dump($arr->copyWithin(-2, -3, -1)); ``` +## Return a string representing the elements in the array using a locale and timezone + +Default locale is en_US, and the timezone is UTC, in order to use a different locale make sure it is installed. + +To check available locales in linux based systems run `locale -a` + +To install a missing locale in linux based systems run `sudo apt-get install language-pack-XX` + +```php +use HiFolks\DataType\Arr; + +$arr = Arr::make([1, 2, 3, 'a', 'abc', 123456.4, '2022/10/01']); +var_dump($arr->toLocaleString()); // Using en_US as default locale and UTC as default timezone +// 1,2,3,a,abc,123,456.40,Sat 01 Oct 2022 12:00:00 AM UTC + +$arr = Arr::make([1, 2, 3, 'a', 'abc', 123456.4, '2022/10/01']); +var_dump($arr->toLocaleString('fr_FR', 'Europe/Paris')); // Using provided locale and timezone +// [1,2,3,a,abc,123 456,40,sam. 01 oct. 2022 00:00:00] +``` + diff --git a/examples/cheatsheet.php b/examples/cheatsheet.php index 5f17b82..f4cb3cb 100644 --- a/examples/cheatsheet.php +++ b/examples/cheatsheet.php @@ -271,3 +271,9 @@ function print_result(mixed $something): void print_result($arr->copyWithin(-2, -3, -1)); // [1, 2, 3, 3, 4] } + +// Return a string representing the elements of the array +$arr = Arr::make([1, 2, 3, 'a', 'abc', 123456.4, '2022/10/01']); + +print_r($arr->toLocaleString()); // Default locale and timezone +print_r($arr->toLocaleString('fr_FR', 'Europe/Paris')); // Provided locale and timezone diff --git a/src/Arr.php b/src/Arr.php index 3b6612b..5ee2458 100755 --- a/src/Arr.php +++ b/src/Arr.php @@ -726,4 +726,63 @@ public function isEmpty(): bool { return $this->length() === 0; } + + /** + * Returns a string representing the elements of the array + * @return string the string representation + */ + public function toLocaleString(string $locale = 'en_US', string $timezone = 'UTC'): string + { + if ($this->isEmpty()) { + return ''; + } + + $fallbackLocale = 'en_US'; + date_default_timezone_set($timezone); + $currentLocale = setlocale(LC_ALL, $locale.'.utf8'); + + if (!$currentLocale) { + $currentLocale = setlocale(LC_ALL, $fallbackLocale.'.utf8'); + } + + $localeConfig = localeconv(); + + $result = $this->map(function ($item) use ($localeConfig) { + if (is_numeric($item)) { + $item = number_format( + $item, + is_float($item) ? 2 : 0, + $localeConfig['decimal_point'] ?? '.', + $localeConfig["thousands_sep"] ?? ',' + ); + } elseif ($this->isDate($item)) { + $date = date_parse($item); + $item = strftime( + '%c', + mktime($date['hour'], $date['minute'], $date['second'], $date['month'], $date['day'], $date['year']) + ); + } + + return $item; + }); + + return $result->toString(); + } + + /** + * Checks whether a value is a valid date + * @return boolean true if value is a valid date, false otherwise + */ + private function isDate($value): bool + { + if (!$value) { + return false; + } + + $date = date_parse($value); + + return $date['error_count'] == 0 + && $date['warning_count'] == 0 + && checkdate($date['month'], $date['day'], $date['year']); + } } diff --git a/tests/ArrTest.php b/tests/ArrTest.php index db420da..b607cbd 100644 --- a/tests/ArrTest.php +++ b/tests/ArrTest.php @@ -1,6 +1,6 @@ length())->toEqual(4); expect($result->arr())->toEqual([2, 4, 6, 8]); }); + +it('tests setLocaleString() returns an empty string for empty array', function () { + $arr = Arr::make([]); + + $result = $arr->toLocaleString(); + expect($result) + ->toBeString() + ->toEqual(''); +}); + +it("tests setLocaleString() returns a string representing the elements of the array", function () { + $arr = Arr::make(['🥝', '🍎', 'I_DONT_KNOW', 1, 2, 3]); + + $result = $arr->toLocaleString(); // 'en_US', 'UTC' + expect($result) + ->toBeString() + ->toEqual('🥝,🍎,I_DONT_KNOW,1,2,3'); +}); + +it("tests setLocaleString() transforms dates and numbers using default locale and timezone", function () { + $arr = Arr::make([-123897.23, +123456.03, 'a', '2022-10-01']); + + $result = $arr->toLocaleString(); // 'en_US', 'UTC' + expect($result) + ->toBeString() + ->toEqual('-123,897.23,123,456.03,a,Sat 01 Oct 2022 12:00:00 AM UTC'); +}); + +it("tests setLocaleString() transforms dates and numbers using provided locale and timezone when available", function () { + $arr = Arr::make([-123897.23, +123456.03, 'a', '2022-10-01']); + + $envLocale = setlocale(LC_ALL, 'fr_FR.utf8'); + $result = $arr->toLocaleString('fr_FR', 'Europe/Paris'); + + if ($envLocale) { + expect($result) + ->toBeString() + ->toEqual('-123 897,23,123 456,03,a,sam. 01 oct. 2022 00:00:00'); + } +}); + +it("tests setLocaleString() transforms dates and numbers using default locale if provided locale is not available", function () { + $arr = Arr::make([-123897.23, +123456.03, 'a', '2022-10-01']); + + $result = $arr->toLocaleString('foo_BAR', 'Europe/Paris'); + expect($result) + ->toBeString() + ->toEqual('-123,897.23,123,456.03,a,Sat 01 Oct 2022 12:00:00 AM CEST'); +}); + +it("tests setLocaleString() skips nulls and invalid dates", function () { + $arr = Arr::make(['product', 123456.4, null, '2020-14-14']); + + $result = $arr->toLocaleString(); + expect($result) + ->toBeString() + ->toEqual('product,123,456.40,,2020-14-14'); +});