I am using IntlDateFormatter/i18n for the first time. When I want to format a date in french, I get the right format (dd/MM/yyyy) but when I am looking for an italian format (for exemple) I get a wrong format (dd/MM/yy) instead of the same as the french one.
Is that a bug of IntlDateFormatter? Do I do something wrong?
Here is a code sample :
<?php
$fmt = new IntlDateFormatter('fr_FR', IntlDateFormatter::SHORT, IntlDateFormatter::NONE);
echo $fmt->getPattern(); // return dd/MM/yyyy
$fmt = new IntlDateFormatter('it_IT', IntlDateFormatter::SHORT, IntlDateFormatter::NONE);
echo $fmt->getPattern(); // return dd/MM/yy instead of dd/MM/yyyy
Here are where I picked up my information, for the date format in France and Italy and for the IntlDateFormatter patterns
for me with php5.5 and lib-icu 4.2.1 both nations give me dd/MM/yy, so if you want a different pattern I suggest to create an array upstream and go with your calling setPattern.
I guess the problem comes from the version of libicu in your system but I'm not 100% sure.
Related
Is there a PHP function anywhere which converts between the timezone name (such as those found here: http://php.net/manual/en/timezones.america.php) and the "value" such as Eastern Standard Time, or Pacific Daylight Time?
Not looking to convert between zones, just get the EST, PDT, etc. names given the America/New_York (or other) name. The only similar question I found is for a different language.
If you you install the PHP Internationalization Package, you can do the following:
IntlTimeZone::createTimeZone('America/New_York')->getDisplayName()
This will return the CLDR English standard-long form by default, which is "Eastern Standard Time" in this case. You can find the other options available here. For example:
IntlTimeZone::createTimeZone('Europe/Paris')->getDisplayName(true, IntlTimeZone::DISPLAY_LONG, 'fr_FR')
The above will return "heure avancée d’Europe centrale" which is French for Central European Summer Time.
Be careful to pass the first parameter as true if DST is in effect for the date and time in question, or false otherwise. This is illustrated by the following technique:
$tz = 'America/New_York';
$dt = new DateTime('2016-01-01 00:00:00', new DateTimeZone($tz));
$dst = $dt->format('I');
$text = IntlTimeZone::createTimeZone($tz)->getDisplayName($dst);
echo($text); // "Eastern Standard Time"
Working PHP Fiddle Here
Please note that these strings are intended for display to an end user. If your intent is to use them for some programmatically purpose, such as calling into another API, then they are not appropriate - even if the English versions of some of the strings happen to align. For example, if you are sending the time zone to a Windows or .NET API, or to a Ruby on Rails API, these strings will not work.
If you know the value from your list at (http://php.net/manual/en/timezones.america.php) you can do something like.
<?php
$dateTime = new DateTime();
$dateTime->setTimeZone(new DateTimeZone('America/New_York'));
echo $dateTime->format('T');
?>
For example 22.02.2014 vs 02.22.2014 or 2014.02.22.
strftime already expects a fixed format and just changes text.
Would it be possible (php 5.3 - large infrastructure, not yet updated) to use setlocale and format the date according to local specifications?
$dt = new DateTime($datetime);
$formatter = new IntlDateFormatter($locale, IntlDateFormatter::SHORT, IntlDateFormatter::SHORT);
return $formatter->format($dt);
After digging around, this is the closest i found.
I'm trying to rely on IntlDateFormatter to return the current date in a locale-based format. This means DD/MM/YYYY for it_IT, de_DE, fr_FR... or MM/DD/YYYY for en_US and so on for all the possible locales.
I'm trying to follow the same solution I used to retrieve the current month's name:
$formatter = new IntlDateFormatter("it_IT", IntlDateFormatter::FULL, IntlDateFormatter::FULL);
$formatter->setPattern("MMMM");
return $formatter->format($this);
This code correctly returns "January", "gennaio" etc.
The problem is, I cannot figure out the right pattern to get the date in the current locale format. The ICU User Guide mentions the DateTimePatternGenerator class, and this looks like it! But I cannot find it in PHP.
I would like to avoid a custom, huge switch-case and rely on built-in function instead.
It must be pure PHP.
Any help?
I'm not sure if you want to get pattern from ICU itself, or just format your DateTime. Here you have both solutions.
Basics:
You're doing well with you actual code for retrieving month name. IntlDateFormatter is pretty customizable, and it all depend on options you gave it.
Getting date with year, month and day depending on locale:
$locale = "en_GB";
$dateType = IntlDateFormatter::SHORT;//type of date formatting
$timeType = IntlDateFormatter::NONE;//type of time formatting setting to none, will give you date itself
$formatter =new IntlDateFormatter($locale, $dateType, $timeType);
$dateTime = new DateTime("2015-02-28");
echo $formatter->format($dateTime);
will give you
28/02/2015
You can play with other options of IntlDateFormatter. There's SHORT, MEDIUM, LONG, FULL and NONE - you can read about them and check example ouput here.
Getting pattern from formatter
$formatter->->getPattern();
will give you something like
dd/MM/yyyy
I hope this will help you. I've been struggling with it for a long time to do it properly :)
Sorry if this is a dupe - lots of similar questions but obviously if I could find an exact answer I wouldn't be asking :)
Note I'm coming from .Net and am a PHP newbie, so there may be noob-scale errors.
I would like to be able to output e.g. new DateTime('2014-01-01 13:15:00') as:
'Wednesday the 1st of January 2014 at 1:15PM' (possible - non-localized) or 'Mercredi 1er Janvier 2014 à 13h15' (not possible?).
Basically, there seems to be no ISO formatting equivalent to PHP's 'S' date format specifier, nor is there one for strftime?
The IntlDateFormatter::FULL comes close - but 'Wednesday, 1 January' or 'mercredi 1 janvier' is not good English (or French) - but it seems to be the closest that I can get? I could live without the 'on', 'the' and 'at' if I had to, but ordinal suffixes would be nice. ('Wednesday one January' - what's that, the beginning to a poem?)
I did see one example on the strftime section comments on PHP.net addressing this issue (which seems to suggest that it is an issue) - however it only seemed to add the English suffixes, which didn't seem much use? I'd like a simple method that takes a UTC datetime, a locale and a timezone and outputs a localized string - preferably in 'proper' human-readable format (as above) as is possible in English. I'd like to achieve this without writing a format string for every language in the world. It would also be nice if it worked on my Windows dev box as well as the *nix production box.
<?php
$utcdate = new DateTime('2014-01-01 13:15:00', new DateTimeZone('UTC'));
echo $utcdate->format('l \t\h\e jS \o\f F Y \a\t g:ia') . "<br>";
function dumpDates($date, $locale, $tz){
$date->setTimeZone(new DateTimeZone($tz));
$fmt = new IntlDateFormatter( $locale, IntlDateFormatter::FULL, IntlDateFormatter::FULL,
$tz, IntlDateFormatter::GREGORIAN );
echo $fmt->format($date) . "<br>";
// doesn't work under windows?
setLocale(LC_TIME, $locale);
echo strftime('%A, %#d %B %Y %I:%M:%S %p', $date->getTimeStamp()) . "<br>";
}
dumpDates($utcdate, 'en_GB', 'Europe/London');
dumpDates($utcdate, 'de_DE', 'Europe/Berlin');
dumpDates($utcdate, 'fr_FR', 'Europe/Paris');
?>
The full part of this question - including full grammatical legibility - would be very difficult to do without either, as you say, writing a format string for every language in the world, or finding a library that contains such strings. MomentJs seems to provide great intl support, but after a cursory search, I haven't been able to find a PHP equivalent, other than the intl extension.
You could get to the stage of providing an internationalised form including ordinal-based number by using a combination of IntlDateFormatter and NumberFormatter, by first using NumberFormatter to get the pattern for the date's ordinal suffix/prefix:
$numFmt = new NumberFormatter('fr_FR', NumberFormatter::ORDINAL);
$ordinalDay = $numFmt->format($date->format('j'));
You could then create a IntlDateFormatter that allows you to retrieve the pattern for the Full date format of the target language:
$dateFormat = new IntlDateFormatter('fr_FR', IntlDateFormatter::FULL, IntlDateFormatter::FULL, $tz, IntlDateFormatter::GREGORIAN);
$datePattern = $dateFormat->getPattern();
Finally, you would need to replace the section in the $datePattern representing the day with the escaped ordinal day pattern:
$datePattern = preg_replace('/d+', "'"+$ordinalDay+"'", $datePattern);
$dateFormat->setPattern($datePattern);
$outputDate = $dateFormat->format($date);
Note that the pattern used by IntlDateFormatter is different from the usual PHP date formatting format codes, here is the documentation for the codes recognised.
A warning; in internationalised formats that are fairly rigidly standardized, an ordinal number would look out of place. For example in chinese, the format is:
y年M月d日EEEE
and inserting the ordinal prefix that exists for written Chinese before the day value may look odd to a Chinese reader.
I have a requirement to change the order of DD/MM/YYYY tags according to a users country .
http://en.wikipedia.org/wiki/Date_format_by_country
The way that I was thinking to do this is to create a country / Dateformat table and according to the country selection to move the fields around using jquery .
Is there an existing way for this to be done in php or even in js or a better approach ?
I was also looking for a table of country/ dateformat rather than inserting all the values manually but I couldn't find anything ...
For PHP, this should be a good start: http://php.net/manual/en/function.setlocale.php
For JavaScript: Display date/time in user's locale format and time offset
All in all, most modern languages have locale support built-in very well. You should not have to implement this yourself. It will be tiresome and buggy (localization is hard).
if you use PHP then the IntlDateFormatter() helps you out:
$d = new DateTime();
$fmt = new IntlDateFormatter('en-US', IntlDateFormatter::SHORT, IntlDateFormatter::NONE);
echo "US: ".$fmt->format($d)."<br/>";
$fmt = new IntlDateFormatter('en-GB', IntlDateFormatter::SHORT, IntlDateFormatter::NONE);
echo "GB: ".$fmt->format($d)."<br/>";
$fmt = new IntlDateFormatter('en-AU', IntlDateFormatter::SHORT, IntlDateFormatter::NONE);
echo "AU: ".$fmt->format($d)."<br/>";
$fmt = new IntlDateFormatter('de-DE', IntlDateFormatter::SHORT, IntlDateFormatter::NONE);
echo "DE: ".$fmt->format($d)."<br/>";
Output:
US: 2/1/18
GB: 01/02/2018
AU: 1/2/18
DE: 01.02.18
If you want to change the format of a date on the client side, you can try the toLocaleString function on the Date object in JavaScript. The toLocaleString will change the format based on the client OS's settings for their location. You also would not need to have a table with the country and date format.
This can be done without the need for jQuery or any additional plugin.