From 3e3b87be90b2f5722e16639f1b23b0eb03328b6f Mon Sep 17 00:00:00 2001 From: elhaj abid Date: Sun, 16 Oct 2022 16:08:01 +0100 Subject: [PATCH 01/12] doc: add toLocaleString() documentatio - Add method description to arr.md - Add method use case example to cheatsheet.php --- doc/arr.md | 20 ++++++++++++++++++++ examples/cheatsheet.php | 6 ++++++ 2 files changed, 26 insertions(+) diff --git a/doc/arr.md b/doc/arr.md index 54059a9..2f6965c 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.utf8", "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..7b367e5 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.utf8', 'Europe/Paris')); // Provided locale and timezone From fbf2e51a38814eba04976ac40fc9b2f34f908d4e Mon Sep 17 00:00:00 2001 From: elhaj abid Date: Sun, 16 Oct 2022 16:12:16 +0100 Subject: [PATCH 02/12] test: add unit tests for toLocaleString() --- tests/ArrTest.php | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/tests/ArrTest.php b/tests/ArrTest.php index db420da..c7db86f 100644 --- a/tests/ArrTest.php +++ b/tests/ArrTest.php @@ -625,3 +625,48 @@ expect($result->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(); + 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.utf8', '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", function () { + $arr = Arr::make([-123897.23, +123456.03, 'a', '2022-10-01']); + + $result = $arr->toLocaleString('fr_FR.utf8', 'Europe/Paris'); + expect($result) + ->toBeString() + ->toEqual('-123 897,23,123 456,03,a,sam. 01 oct. 2022 00:00:00'); +}); + +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'); +}); From e234332d897f04d2fc7997f07c489a25dd0f34aa Mon Sep 17 00:00:00 2001 From: elhaj abid Date: Sun, 16 Oct 2022 19:46:58 +0100 Subject: [PATCH 03/12] feat: implement toLocaleString() method --- src/Arr.php | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/Arr.php b/src/Arr.php index 3b6612b..ebc6f8f 100755 --- a/src/Arr.php +++ b/src/Arr.php @@ -726,4 +726,57 @@ 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($locale = 'en_US.utf8', $timezone = 'UTC'): string + { + if ($this->length() <= 0) { + return ''; + } + + date_default_timezone_set($timezone); + $currentLocale = setlocale(LC_ALL, $locale); + $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 + */ + protected 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']); + } } From e45b6a18b55245ead8ac366d160257e28e445368 Mon Sep 17 00:00:00 2001 From: elhaj abid Date: Sun, 16 Oct 2022 19:47:55 +0100 Subject: [PATCH 04/12] chore: update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) 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: From d624b1bdb7f7c8478d0ff39ce8595f461a084333 Mon Sep 17 00:00:00 2001 From: elhaj abid Date: Sat, 22 Oct 2022 12:54:10 +0100 Subject: [PATCH 05/12] refactor: use existing helper to check for empty arrays --- src/Arr.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Arr.php b/src/Arr.php index ebc6f8f..7def680 100755 --- a/src/Arr.php +++ b/src/Arr.php @@ -733,7 +733,7 @@ public function isEmpty(): bool */ public function toLocaleString($locale = 'en_US.utf8', $timezone = 'UTC'): string { - if ($this->length() <= 0) { + if ($this->isEmpty()) { return ''; } From a52c56ea25a769dfda6af96c7cbc6e41429cfda6 Mon Sep 17 00:00:00 2001 From: elhaj abid Date: Sat, 22 Oct 2022 12:57:11 +0100 Subject: [PATCH 06/12] fix: add type hints to function params --- src/Arr.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Arr.php b/src/Arr.php index 7def680..9d458e2 100755 --- a/src/Arr.php +++ b/src/Arr.php @@ -731,7 +731,7 @@ public function isEmpty(): bool * Returns a string representing the elements of the array * @return string the string representation */ - public function toLocaleString($locale = 'en_US.utf8', $timezone = 'UTC'): string + public function toLocaleString(string $locale = 'en_US.utf8', string $timezone = 'UTC'): string { if ($this->isEmpty()) { return ''; From 0b5288fa4b86d87956bf78b7e06677bbc12e3f6e Mon Sep 17 00:00:00 2001 From: elhaj abid Date: Sat, 22 Oct 2022 13:24:15 +0100 Subject: [PATCH 07/12] fix: use fallback locale if provided locale is not available --- src/Arr.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Arr.php b/src/Arr.php index 9d458e2..a1cc86a 100755 --- a/src/Arr.php +++ b/src/Arr.php @@ -731,14 +731,20 @@ public function isEmpty(): bool * Returns a string representing the elements of the array * @return string the string representation */ - public function toLocaleString(string $locale = 'en_US.utf8', string $timezone = 'UTC'): string + 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); + $currentLocale = setlocale(LC_ALL, $locale.'.utf8'); + + if (!$currentLocale) { + $currentLocale = setlocale(LC_ALL, $fallbackLocale.'.utf8'); + } + $localeConfig = localeconv(); $result = $this->map(function ($item) use ($localeConfig) { From affba46c1aca38880a465b5df9c4b1edf2baf4e7 Mon Sep 17 00:00:00 2001 From: elhaj abid Date: Sat, 22 Oct 2022 13:46:13 +0100 Subject: [PATCH 08/12] test: update tests to account for unavailable locales --- tests/ArrTest.php | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/tests/ArrTest.php b/tests/ArrTest.php index c7db86f..b607cbd 100644 --- a/tests/ArrTest.php +++ b/tests/ArrTest.php @@ -1,6 +1,6 @@ toLocaleString(); + $result = $arr->toLocaleString(); // 'en_US', 'UTC' expect($result) ->toBeString() ->toEqual('🥝,🍎,I_DONT_KNOW,1,2,3'); @@ -647,19 +647,32 @@ 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.utf8', 'UTC' + $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", function () { +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']); - $result = $arr->toLocaleString('fr_FR.utf8', 'Europe/Paris'); - expect($result) + $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 () { From 86627c0fce807e1c8c8fddf6b3965a0771890cdc Mon Sep 17 00:00:00 2001 From: elhaj abid Date: Sat, 22 Oct 2022 14:02:27 +0100 Subject: [PATCH 09/12] fix: updates cheatsheet example --- examples/cheatsheet.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/cheatsheet.php b/examples/cheatsheet.php index 7b367e5..f4cb3cb 100644 --- a/examples/cheatsheet.php +++ b/examples/cheatsheet.php @@ -276,4 +276,4 @@ function print_result(mixed $something): void $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.utf8', 'Europe/Paris')); // Provided locale and timezone +print_r($arr->toLocaleString('fr_FR', 'Europe/Paris')); // Provided locale and timezone From 7b1419d552cbc6288dd19fdb85498ce21ee0fb3a Mon Sep 17 00:00:00 2001 From: elhaj abid Date: Sat, 22 Oct 2022 14:03:30 +0100 Subject: [PATCH 10/12] doc: update toLocaleString() docs --- doc/arr.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/arr.md b/doc/arr.md index 2f6965c..cc19350 100644 --- a/doc/arr.md +++ b/doc/arr.md @@ -395,12 +395,12 @@ To install a missing locale in linux based systems run `sudo apt-get install lan ```php use HiFolks\DataType\Arr; -$arr = Arr::make([1, 2, 3, 'a', 'abc', 123456.4, "2022/10/01"]); +$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.utf8", "Europe/Paris")); // Using provided locale and timezone +$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] ``` From 2f1074fe936e575c0e11f79f58bfa5812fe41489 Mon Sep 17 00:00:00 2001 From: elhaj abid Date: Sat, 22 Oct 2022 14:04:16 +0100 Subject: [PATCH 11/12] style: run composer format --- src/Arr.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Arr.php b/src/Arr.php index a1cc86a..61c1e72 100755 --- a/src/Arr.php +++ b/src/Arr.php @@ -742,7 +742,7 @@ public function toLocaleString(string $locale = 'en_US', string $timezone = 'UTC $currentLocale = setlocale(LC_ALL, $locale.'.utf8'); if (!$currentLocale) { - $currentLocale = setlocale(LC_ALL, $fallbackLocale.'.utf8'); + $currentLocale = setlocale(LC_ALL, $fallbackLocale.'.utf8'); } $localeConfig = localeconv(); From 3b5ed535b780cb0571f8405cb7aa2c564549adb6 Mon Sep 17 00:00:00 2001 From: elhaj abid Date: Sat, 22 Oct 2022 14:07:26 +0100 Subject: [PATCH 12/12] refactor: change helper to private --- src/Arr.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Arr.php b/src/Arr.php index 61c1e72..5ee2458 100755 --- a/src/Arr.php +++ b/src/Arr.php @@ -773,7 +773,7 @@ public function toLocaleString(string $locale = 'en_US', string $timezone = 'UTC * Checks whether a value is a valid date * @return boolean true if value is a valid date, false otherwise */ - protected function isDate($value): bool + private function isDate($value): bool { if (!$value) { return false;