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

LocalDate::format #3

Open
solodkiy opened this issue Mar 10, 2018 · 12 comments
Open

LocalDate::format #3

solodkiy opened this issue Mar 10, 2018 · 12 comments

Comments

@solodkiy
Copy link
Contributor

Common task is convert date for human readability format, or some special format like 'd.m.y' and I don't see how I can do this with this class. Did I miss some formatter class or this behavior don't implemented?

@BenMorel
Copy link
Member

Hi, this is not yet implemented in the library itself. I'm using a DateTimeFormatter class in my projects for this purpose.

It's based on intl and therefore accepts a locale rather than a 'd.m.y' string.

It's not yet merged into the library because there are several ways to format a given date or time even for a single locale, and this class allows only one. Examples in fr_FR:

Date:

  • 11/03/18
  • 11/03/2018

Time:

  • 12:30
  • 12:30:00
  • 12:30:00.000000000

And for date/time, a combination of those (6 possibilities at least).
So the only thing to do to implement the formatter in the library is to find a clean API for these settings.

BTW, do you have a special requirement for setting explicitly the date/time format like d.m.y, or would the locale-based format be OK for you?

@solodkiy
Copy link
Contributor Author

I really need setting explicitly the date/time format like d.m.y because I can't control formats what other services expecting from me. For me parse and print date/time from custom formats is must have functionality.

@BenMorel
Copy link
Member

Some update: there is still no built-in way to parse and format from a format string just like PHP does; however, there are now methods to convert objects to and from native DateTime objects:

  • fromDateTime()
  • toDateTime()

These methods are available in version 0.1.7 in the following classes:

  • LocalDate
  • LocalTime
  • LocalDateTime
  • ZonedDateTime

Although this is suboptimal, you can use these methods to achieve what you want, in the meantime:

$localDate = LocalDate::of(2017, 10, 18);
echo $localDate->toDateTime()->format('d/m/y'); // 18/10/17

@jiripudil
Copy link
Contributor

jiripudil commented Nov 22, 2018

Hello there. We faced a similar issue at work, so let me throw in my two cents:

Common task is convert date for human readability format

A common task indeed!

So the only thing to do to implement the formatter in the library is to find a clean API for these settings.

Why not draw again from the apparent source of inspiration for this library? The API of Java's DateTimeFormatter closely resembles the parsing mechanism that's already implemented here (obviously so, because Java uses the very same class for both parsing and formatting) – couldn't the formatting API be ported in a similar way?

Just a concept of what the API might look like, sans builders and other utilities:

$localDate = LocalDate::of(2018, 11, 6);
$localDate->format(IsoFormatters::localDate()); // 2018-11-06
$localDate->format(PatternFormatter::of('d. M. yyyy')); // 6. 11. 2018
$localDate->format(LocalizedFormatter::ofDate('fr_FR', LocalizedFormatter::SHORT)) // 06/11/18

It looks versatile enough while still allowing for a certain level of strictness, and it's already somewhat proven by Java users. What do you think about such API?

@BenMorel
Copy link
Member

I'm definitely in favour of adding a formatting API.

I think we should start with the easiest part IMO, which is what the OP requested: a custom formatter that accepts strings such as d. M. yyyy.

The locale-based formatter is more obscure regarding possible formats, and I think we should discuss it in a separate thread.

The only thing we need, is to define the alphabet used for formatting. One idea would be to mimic PHP's date() alphabet, but we'll have to modify it somehow for things like nanos, which have no equivalent in PHP.

Another approach, which I'd favour as this project was inspired by Java indeed, is to use their alphabet instead (or a subset of it, at least: we don't implement "era" for example). They have a different approach from PHP, which is that a single letter can have several outputs depending on its repetition:

Format PHP Java
2018-02-01 Y-m-d yyyy-MM-dd
1/2/18 j/n/y d/M/yy

I quite like their approach. What do you think?

@pupitooo
Copy link

I like Java approach too, but mixing notations seems to me like a bad idea.
This is PHP library, so I think it should take PHP notation about date.

@jiripudil
Copy link
Contributor

jiripudil commented Nov 25, 2018

The locale-based formatter is more obscure regarding possible formats

That, I believe, both is and isn't true. Let me just bring a related thought to light: In Java, some symbols in the pattern formatter such as DOW or month names are also locale-based. I'll elaborate below.

Another approach is to use their [Java's] alphabet instead

I like it more, too. I find the use of repetition much more obvious, as in d vs dd, as opposed to PHP's j vs d. The point about inconsistency with date() is sound, but the Java's alphabet is so much better grounded in standards; in fact, it uses a SimpleDateFormat as defined by the ICU. Getting back to the previous point about locale-based formatter, the very same ICU document also describes the SHORT, MEDIUM, LONG and FULL formats of localised dates and times, as used by what I call the LocalizedFormatter in the API concept in my previous comment.

With the ICU format syntax – which can be used quite easily in PHP with the intl extension – the pattern-based formatter would be able to deal with the localised format obscurities on its own, and the LocalizedFormatter could be kept for convenient usage of the pre-defined formats. At least that's how Java uses it afaik.

There are, of course, drawbacks. For example the "era", while not implemented, is supported in the format syntax and the PHP's intl extension formats it correctly, so there would be inconsistencies. Also, implementation-wise, using IntlDateFormatter and DateTimes for formatting might throw away the benefits of the abstraction, bringing in problems such as how to detect when a HH:mm:ss formatter is used to format a LocalDate (which should throw an exception).

So yes, maybe a subset of the alphabet and some more custom implementation will be necessary, but in general, this is the direction that makes sense to me for the formatting API to take.

@solodkiy
Copy link
Contributor Author

solodkiy commented Dec 1, 2018

My vote for php-notation. Easy to implement (without any extensions), known by all php programmers.

@solodkiy
Copy link
Contributor Author

solodkiy commented Apr 5, 2020

Ok. Moving forward. This is quite unrelated from this issue, but also connected. We talk about date representation.

I have ZonedDateTime in some timezone (perhaps UTC, perhaps not) and I need to write it in xlsx report in Moscow timezone in some date format.
Convert to LocaTime in some point seems logical. What can I do right now?
$zonedDate->withTimeZoneSameInstant(TimeZone::parse('Europe/Moscow'))->getDateTime()->toDateTimeImmutable()->format('Y-m-d H:i:s');
Looks quite monstrous.

What I am looking for:
$zonedDate->getDateTime(TimeZone::parse('Europe/Moscow'))->format('Y-m-d H:i:s');
suggestion that getDateTime can convert zonned date to given time zone.
Or even $zonedDate->format('Y-m-d H:i:s', TimeZone::parse('Europe/Moscow'));

@solodkiy
Copy link
Contributor Author

solodkiy commented Apr 9, 2020

@BenMorel are you ok with adding optional TimeZone argument to Zoned getDateTime, getDate and getTime methods?

@BenMorel
Copy link
Member

BenMorel commented Apr 9, 2020

@solodkiy I don't see the point, I'm sorry? It sounds more logical to convert the ZonedDateTime to the timezone you want, then format as appropriate?

@antonkomarev
Copy link

antonkomarev commented Aug 29, 2020

Another one possible approach - create classes which formats dates when converting object to string.

final class Rfc3339FormatZonedDateTime
{
    private ZonedDateTime $dateTime;

    public function __constructor(ZonedDateTime $dateTime)
    {
        $this->dateTime = $dateTime;
    }

    public function __toString(): string
    {
        // Make formatting logic here and return it
    }
}

Then API of the main classes wouldn't be affected and we will be able to introduce set of default formatters and developer will be able to create new formats for their needs.

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

5 participants