Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ADD recognize weeks #2617

Closed
allanlaal opened this issue May 26, 2022 · 2 comments
Closed

ADD recognize weeks #2617

allanlaal opened this issue May 26, 2022 · 2 comments

Comments

@allanlaal
Copy link
Contributor

allanlaal commented May 26, 2022

Hello,

I encountered an issue with the following code:

echo Carbon::parse('week 23')->format('Y-m-d H:i:s');

Carbon version: 2.57.0; 2.x-dev; 3.x-dev

PHP version: https://try-carbon.herokuapp.com/

I expected to get:

first day of week for week 23

But I actually get:

Error: Could not parse 'week 23': Failed to parse time string (week 23) at position 0 (w): The timezone could not be found in the database

examples of week formats (that all failed with Carbon):

week nr 23
wk 23
week №23
week # 23
W23
2022#23
first day 9 AM of 2022#23
week number 23
first day 9 AM of 2022 week number 23
2022 week 23 first day 9 AM
2022 week nr 23
@kylekatarnls
Copy link
Collaborator

kylekatarnls commented May 29, 2022

Hello,

While I perfectly understand how such feature could be useful, I'm not sure it has to be on a global library. It sure exists many ways to refer to a particular day/moment and the more we add, the longest it will take to parse and the more we'll have possible conflicts and ambiguities. We don't have for instance Christmas.

Also for consistency, we try to implement for each English syntax in parse() the equivalent in supported languages for parseFromLocale, for instance we would need Carbon::parseFromLocale('semaine numéro 23', 'fr') to be supported if we want it consistent and support Carbon::parse('week number 23') and while "week" is a word we already have in translations, "number" would be new and need some significant translation effort.

However the ISO format is supported (e.g. '2022W23') which means from application side, you can replace all the possible syntaxes with the ISO format:

$syntaxes = [
    'week nr 23',
    'wk 23',
    'week №23',
    'week # 23',
    'W23',
    '2022#23',
    'first day 9 AM of 2022#23',
    'week number 23',
    'first day 9 AM of 2022 week number 23',
    '2022 week 23 first day 9 AM',
    '2022 week nr 23',
];

foreach ($syntaxes as $syntax) {
    $dateString = preg_replace('/(?:[Ww]eeks?|[Ww]k)\s+(?:(?:[Nn]umber|№|[Nn][r°]?|#)\s*)?(\d+)/', 'W$1', $syntax);
    $dateString = preg_replace('/(\d{4})\s*[#W](\d+)/', '$1W$2', $dateString);
    $dateString = preg_replace('/(?<!\d)W(\d+)/', date('Y') . 'W$1', $dateString);
    $dateString = preg_replace('/^(.*)\s+of\s+(\d{4}W\d+)/', '$2 $1', $dateString);

    echo $dateString . "\n";
    echo Carbon::parse($dateString) . "\n\n";
}

And They all become strings that Carbon can parse:

2022W23
2022-06-06 00:00:00

2022W23
2022-06-06 00:00:00

2022W23
2022-06-06 00:00:00

2022W23
2022-06-06 00:00:00

2022W23
2022-06-06 00:00:00

2022W23
2022-06-06 00:00:00

2022W23 first day 9 AM
2022-06-07 09:00:00

2022W23
2022-06-06 00:00:00

2022W23 first day 9 AM
2022-06-07 09:00:00

2022W23 first day 9 AM
2022-06-07 09:00:00

2022W23
2022-06-06 00:00:00

One more replacement step allow you to support translation from a given locale:

$syntaxes = [
    'semaine num. 23',
    'sem. 23',
    'semaine №23',
    'semaine # 23',
    'W23',
    '2022#23',
    'first day 9 AM of 2022#23',
    'semaine numéro 23',
    'first day 9 AM of 2022 semaine numéro 23',
    '2022 semaine 23 first day 9 AM',
    '2022 semaine num. 23',
];

foreach ($syntaxes as $syntax) {
    $dateString = Carbon::translateTimeString($syntax, 'fr', 'en');
    $dateString = preg_replace('/sem./i', 'wk', $dateString);
    $dateString = preg_replace('/(num\.|numéro)/i', 'number', $dateString);
    $dateString = preg_replace('/(?:[Ww]eeks?|[Ww]k)\s+(?:(?:[Nn]umber|№|[Nn][r°]?|#)\s*)?(\d+)/', 'W$1', $dateString);
    $dateString = preg_replace('/(\d{4})\s*[#W](\d+)/', '$1W$2', $dateString);
    $dateString = preg_replace('/(?<!\d)W(\d+)/', date('Y') . 'W$1', $dateString);
    $dateString = preg_replace('/^(.*)\s+of\s+(\d{4}W\d+)/', '$2 $1', $dateString);

    echo $dateString . "\n";
    echo Carbon::parse($dateString) . "\n\n";
}

=> Same result.

It think this could remain in application business logic, or be the subject of a dedicated macro/library (so you would execute all those replacements only when you specifically want to support human-week strings from the input).

Thanks.

@allanlaal
Copy link
Contributor Author

continued in: jenssegers/date#345

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants