I have a function that reads out the date in a file on the first line. This date is formatted in dutch like this 2 mei 2013 or 28 jun. 2013
It needs to convert the date string into a timestamp, but whatever i try it won't work for the mei moths or any other dutch named month. Here is the code I currently have (the original function is a bit more code, but this is where it goes wrong)
function getTimestamp($date){
date_default_timezone_set('Europe/Amsterdam');
setlocale(LC_ALL, 'nl_NL');
$timestamp = strtotime($date);
return $timestamp;
}
Now, here are some results when using this function:
$timestamp = getTimestamp('28 jun. 2013') //1372370400
$timestamp2 = getTimestamp('2 mei 2013') // false
but, when i put this code in the function
echo strftime('%e %b %Y', 1367445600)."\n";
it prints '2 mei 2013'
How can I tell php not only format the date-time string in Dutch, but also read it in Dutch?
=======================
Thanks to some explanation below I now have the code working (this is the full function)
public function getReportDate(){
$mothsTranslated = array('mrt'=> 'mar','mei'=>'may', 'okt'=>'oct');
$content = file($this->file);
$line = $content[0];
$header = str_getcsv($line, $this->delimiter);
$date = str_replace('.', '', $header[1]);
foreach ($mothsTranslated as $dutch => $eng) {
if(strpos($date, $dutch) !== false){
$date = str_replace($dutch, $eng, $date);
}
}
$timestamp = strtotime($date);
return $timestamp;
}
Without creating your own date parser, the native PHP functions only use English dates.
However, there is an international dateformatter extension available for PHP. You can install this plugin and then would be able to parse non-english dates.
http://www.php.net/manual/en/intldateformatter.parse.php
As others found out, strtotime does not respect the set locale.
Indeed, it's description in the manual states: "Parse about any English textual datetime description into a Unix timestamp"
Solutions
You can use strptime() since PHP5 that does respect the locale (like strftime), but there are some warnings about using it on the php website.
You could write a function that replaces the Dutch month names to English month names and then calls strtotime.
Related
I have a DateTime object which I'm currently formating via
$mytime->format("D d.m.Y")
Which gives me exactly the format I need:
Tue 5.3.2012
The only missing point is the correct language. I need German translation of Tue (Tuesday), which is Die (Dienstag).
This gives me the right locale setting
Locale::getDefault()
But I don't know how to tell DateTime::format to use it.
Isn't there a way to do something like:
$mytime->format("D d.m.Y", \Locale::getDefault());
You can use the Intl extension to format the date. It will format dates/times according to the chosen locale, or you can override that with IntlDateFormatter::setPattern().
A quicky example of using a custom pattern, for your desired output format, might look like.
$dt = new DateTime;
$formatter = new IntlDateFormatter('de_DE', IntlDateFormatter::SHORT, IntlDateFormatter::SHORT);
$formatter->setPattern('E d.M.yyyy');
echo $formatter->format($dt);
Which outputs the following (for today, at least).
Di. 4.6.2013
That's because format does not pay attention to locale. You should use strftime instead.
For example:
setlocale(LC_TIME, "de_DE"); //only necessary if the locale isn't already set
$formatted_time = strftime("%a %e.%l.%Y", $mytime->getTimestamp())
IntlDateFormatter is the way to go currently (2023).
<?php
$formatter = new IntlDateFormatter(
$locale, // the locale to use, e.g. 'en_GB'
$dateFormat, // how the date should be formatted, e.g. IntlDateFormatter::FULL
$timeFormat, // how the time should be formatted, e.g. IntlDateFormatter::FULL
'Europe/Berlin' // the time should be returned in which timezone?
);
echo $formatter->format(time());
Will give a different output, depending on what you pass as $locale and the date and time format. I wanted to add some samples for future reference. Note that IntlDateFormatter::GREGORIAN and IntlDateFormatter::LONG are interchangable.
Locale: en_US
Format for Date & Time: Results in:
IntlDateFormatter::FULL Friday, August 5, 2022 at 3:26:37 PM Central European Summer Time
IntlDateFormatter::LONG August 5, 2022 at 3:26:37 PM GMT+2
IntlDateFormatter::MEDIUM Aug 5, 2022, 3:26:37 PM
IntlDateFormatter::SHORT 8/5/22, 3:26 PM
Locale: en_GB
Format for Date & Time: Results in:
IntlDateFormatter::FULL Friday, 5 August 2022 at 15:26:37 Central European Summer Time
IntlDateFormatter::LONG 5 August 2022 at 15:26:37 CEST
IntlDateFormatter::MEDIUM 5 Aug 2022, 15:26:37
IntlDateFormatter::SHORT 05/08/2022, 15:26
Locale: de_DE
Format for Date & Time: Results in:
IntlDateFormatter::FULL Freitag, 5. August 2022 um 15:26:37 Mitteleuropäische Sommerzeit
IntlDateFormatter::LONG 5. August 2022 um 15:26:37 MESZ
IntlDateFormatter::MEDIUM 05.08.2022, 15:26:37
IntlDateFormatter::SHORT 05.08.22, 15:26
Locale: fr_FR
Format for Date & Time: Results in:
IntlDateFormatter::FULL vendredi 5 août 2022 à 15:26:37 heure d’été d’Europe centrale
IntlDateFormatter::LONG 5 août 2022 à 15:26:37 UTC+2
IntlDateFormatter::MEDIUM 5 août 2022 à 15:26:37
IntlDateFormatter::SHORT 05/08/2022 15:26
As salathe has already said, you can also use $formatter->setPattern to further customize the output if needed.
While setlocale() is the correct answer and will still work but is outdated now.
strftime has been DEPRECATED as of PHP 8.1.0 Relying on this function is highly discouraged.
And mentioned Intl extension works perfectly, but not always handy.
One of the simplest ways to work with dates and times is to use Carbon2, CakePHP Chronos or similar library. It provides a single interface to all date's manipulations, formatting, and calculations. If you work with dates a lot I recommend using Carbon and then doing something like this
$date = Carbon::now()->locale('fr_FR');
echo $date->isoFormat('dd DD.MM.YYYY');
Please note that the format differs from the date() one. Full list see in Carbon docs but mentioned D d.m.Y can be something like dd DD.MM.YYYY.
If your project accepts 3rd party libraries, it's really the way to go. Also, if you're using the framework, please check, maybe Carbon (or its wrapper) is already included.
I made something that just does that, because there doesn't seem to exist a simple solution anywhere online, except for with strftime, which is very much deprecated!
My solution extends DateTime::format() with international month and day names and doesn't require installing a bunch of modules, learning new date formatting ways, etc.
After including the classes provided below you can use it as follows. Instead of
$date = new DateTime("2010-01-01 1:23");
echo $date->format("l (D) Y-M-d (F)");
Result: Friday (Fri) 2010-Jan-01 (January)
You can now use
$date = new DateTimeIntl("2010-01-01 1:23");
echo $date->format("l (D) Y-M-d (F)");
Result: vrijdag (vr) 2010-jan.-01 (januari) (Dutch locale).
You can dynamically change the $datetime->locale if wanted.
$date = new DateTimeIntl("2010-01-01 1:23");
$date->locale = "it_IT" ;
echo $date->format("l (D) Y-M-d (F)");
Result: venerdì (ven) 2010-gen-01 (gennaio)
Include this:
class DateTimePatternReplace {
function __construct(public string $DateTimeCode,
public string $IntDateFormatterCode,
public string $tempDateTimePlaceHolder) {}
}
trait addIntlDate {
public string $locale="nl_NL" ; // REPLACE BY YOUR FAVORITE LOCALE
private function getIntResult(string $pattern) {
if ( ! isset($this->formatter) || $this->formatter->getLocale(Locale::VALID_LOCALE) != $this->locale ) {
$this->formatter = new IntlDateFormatter($this->locale);
$this->locale = $this->formatter->getLocale(Locale::VALID_LOCALE); // store the valid version of the locale
}
this->formatter->setPattern($pattern);
return $this->formatter->format($this);
}
function format(string $pattern): string {
// The third parameter can NOT contain normal latin letters, these are random,
// distinctive codes not likely to be in a date format string
$replacePatterns = [/*weekdays*/new DateTimePatternReplace('l', 'EEEE', '[*ł*]'),
new DateTimePatternReplace('D', 'EEE', '[*Đ*]'),
/*month*/ new DateTimePatternReplace('F', 'MMMM', '[*ƒ*]'),
new DateTimePatternReplace('M', 'MMM', '[*μ*]'),
// add new replacements here if needed
] ;
$codesFound=[] ;
foreach($replacePatterns as $p) {
if ( str_contains($pattern, $p->DateTimeCode)) {
// replace codes not prepended by a backslash.
// known bug: codes prepended by double backslashes will not be translated. Whatever.
$pattern = preg_replace('/(?<!\\\)'.preg_quote($p->DateTimeCode)."/", $p->tempDateTimePlaceHolder, $pattern);
$codesFound[] = $p ;
}
}
$result = parent::format($pattern) ;
foreach($codesFound as $p) {
$code = $this->getIntResult($p->IntDateFormatterCode);
$result = str_replace($p->tempDateTimePlaceHolder, $code, $result);
}
return $result ;
}
}
// you can remove this str_contains addition in PHP 8 or higher
if (!function_exists('str_contains')) {
function str_contains($haystack, $needle) {
return $needle !== '' && mb_strpos($haystack, $needle) !== false;
}
}
// end str_contains addition
class DateTimeIntl extends DateTime {
use addIntlDate;
}
class DateTimeImmutableIntl extends DateTimeImmutable {
use addIntlDate;
}
This code extends DateTime and DateTimeImmutable, extends their normal formatting with a locale. So this keeps everything extremely simple
You can add new patterns to be translated if needed by adding codes to the array: a formatting pattern in DateTime::format()-syntax, a corresponding formatting pattern in IntlDateFormatter::format-syntax, plus a placeholder to be used in DateTime::format that does NOT contains letters/codes/patterns that will be used/replaced by the DateTime::format method. See as example the current four codes that use no letters in ASCII lower than 128 letters. (They do use Polish, Greek, Dutch and Slovak letters just for fun.)
Built and tested in PHP 8.1.
For some older version of PHP you will have to change the first class to
class DateTimePatternReplace {
public string $DateTimeCode;
public string $IntDateFormatterCode;
public string $tempDateTimePlaceHolder;
function __construct(string $DateTimeCode, string $IntDateFormatterCode, string $tempDateTimePlaceHolder) {
$this->DateTimeCode = $DateTimeCode;
$this->IntDateFormatterCode = $IntDateFormatterCode;
$this->tempDateTimePlaceHolder = $tempDateTimePlaceHolder;
}
}
This is how I solved combining the features of DateTime and strftime().
The first allows us to manage strings with a weird date format, for example "Ymd" (stored in db from a datepicker).
The second allows us to translate a date string in some language.
For example we start from a value "20201129", and we want end with an italian readable date, with the name of day and month, also the first letter uppercase: "Domenica 29 novembre 2020".
// for example we start from a variable like this
$yyyymmdd = '20201129';
// set the local time to italian
date_default_timezone_set('Europe/Rome');
setlocale(LC_ALL, 'it_IT.utf8');
// convert the variable $yyyymmdd to a real date with DateTime
$truedate = DateTime::createFromFormat('Ymd', $yyyymmdd);
// check if the result is a date (true) else do nothing
if($truedate){
// output the date using strftime
// note the value passed using format->('U'), it is a conversion to timestamp
echo ucfirst(strftime('%A %d %B %Y', $truedate->format('U')));
}
// final result: Domenica 29 novembre 2020
I am scraping a blog site, until now everything was working fine, but now that the blog site has changed to multi language, now I have a problem scraping the date and time. So help me fix that.
Earlier I used to get the date format from the blog site in different ways as follows.
Thursday, 31 October 2019
Thursday, September 10, 2020
That worked fine for me, as I could convert to PHP in the following ways.
$fetched_date = $info['date']; // which is 'Thursday, 31 October 2019'
$time_stamp = strtotime($fetched_date);
$new_date = date('Y-m-d', $time_stamp);
// It was gave me this date '2019-10-31',
// which is perfect for me, because i can store it to my DB.
But since the blog site has changed to multi-language, I occasionally get a date in another language as follow. So how do I convert it?
गुरुवार, १८ जून, २०२० // mr_IN
ગુરુવાર, 10 સપ્ટેમ્બર, 2020 // gu_IN
So when I try with this date format, it gives me the wrong date, which I can't even use. like,
$fetched_date = $info['date']; // which is 'गुरुवार, १८ जून, २०२०'
$time_stamp = strtotime($fetched_date);
$new_date = date('Y-m-d', $time_stamp);
// It was gave me this date '1970-01-01', which is wrong and i can't store to my DB.
// it should be "2020-06-18"
And when I do scraping I also get a language code like: mr_IN, gu_IN , so how do I get the correct date using that language code?
I want to convert the date in PHP and store it in MySQL, how do I do that?
The IntlDateFormatter class can help here. However, the date format must fit.
$dateString = 'गुरुवार, १८ जून, २०२०';
$timeZone = new DateTimeZone("UTC");
$fmt = new IntlDateFormatter(
'mr_IN',
IntlDateFormatter::FULL,
IntlDateFormatter::NONE,
$timeZone,
IntlDateFormatter::GREGORIAN
);
$ts = $fmt->parse($dateString);
$dateTime = date_create("today",$timeZone)->setTimeStamp($ts);
echo $dateTime->format("Y-m-d"); //2020-06-18
I want to convert 1373892900000 to Monday 2013/07/15 8:55 AM in Codeigniter.
However, I keep receiving a totally different result by converting the timestamp using the function i have written, please note:I need to change the dates according to different timezones, that is why I want to write it this way:
public function time_convert($timestamp){
$this->load->helper('date');
date_default_timezone_set('UTC');
$daylight_saving = TRUE;
$timezone = "UM4"; //toronto or new york timezone
$time = gmt_to_local($timestamp, $timezone, $daylight_saving);
$final_time = standard_date('DATE_RFC822', $time);
return $final_time;
}
Result from the above function is: Sat, 08 Dec 06 01:40:00 +0000
And if I don't put date_default_timezone_set('UTC'); in the above function, I get this date instead Sat, 08 Dec 06 02:40:00 +0100. My codeigniter seems to default the timezone to Europe/Berlin.
Can anyone please help me correct any of the mistakes I might have made?
Why not just use PHP's date function?
public function time_convert($timestamp){
return date('l Y/m/d H:i', $timestamp);
}
For different timezones use a DateTime object:
public function time_convert($timestamp, $timezone = 'UTC'){
$datetime = new DateTime($timestamp, new DateTimeZone($timezone));
return $datetime->format('l Y/m/d H:i');
}
Think that should work. Note: I tihnk you need at least PHP version 5.20 for the TimeZone class.
<?php
$time_str=1373892900000;
echo gmdate("fill with your format", $time_str);
?>
your format = format your time in php, reading this page for details.
http://php.net/manual/en/function.date.php
http://php.net/manual/en/function.gmdate.php
Appears as though an invocation of standard_date with the DATE_ATOM format may sort you:
echo unix_to_human(time(), true, 'us'); # returns 2013-07-12 08:01:02 AM, for example
There are a whole host of other options for the format, enumerated on the linked page.
This how to covert timestamp to date very simple:
echo date('m/d/Y', 1299446702);
to convert timestamp to human readable format try this:
function unix_timestamp_to_human ($timestamp = "", $format = 'D d M Y - H:i:s')
{
if (empty($timestamp) || ! is_numeric($timestamp)) $timestamp = time();
return ($timestamp) ? date($format, $timestamp) : date($format, $timestamp);
}
$unix_time = "1251208071";
echo unix_timestamp_to_human($unix_time); //Return: Tue 25 Aug 2009 - 14:47:51
if you want to convert it to a format like this: 2008-07-17T09:24:17Z than use this method
<?php
$timestamp=1333699439;
echo gmdate("Y-m-d\TH:i:s\Z", $timestamp);
?>
for details about date:
http://php.net/manual/en/function.date.php
Your timestamp is coming from javascript on the client, I would guess, because it appears to be in milliseconds. php timestamps are in seconds. So to get the answer you want, first divide by 1000.
Showing the full year would have made the issue more obvious, as you would have seen the year as 45,506.
So I have the date like this in wordpress, I get it from a custom metabox where is stored like this, 23/02/2012, now how can I set wp_locale in WP or something like that, and I need to convert the date to: Monday 23 February 2012, but I need also to set the language, thats why I need that wp_locale because that output will be in Dutch.Thank you
The date format can be converted with the code below as a guide.
date('l j F Y', strtotime(str_replace('/', '-', '23/02/2012')))
The str_replace is necessary because with / PHP assumes m/d/y American date format, not the European d/m/y.
As for doing this in Wordpress with i18n support, you might consider http://codex.wordpress.org/Function_Reference/date_i18n
date_i18n('l j F Y', strtotime(str_replace('/', '-', '23/02/2012')))
I guess there are other ways to do this, but I'd do it as follows:
Upon 'save_post':
$date = explode ('/',$_POST["date_field"]);
$date = $date[1].'/'.$date[0].'/'.$date[2]; // dd/mm/yyyy to mm/dd/yyyy
$s = strtotime($date); /* UNIX TIMESTAMP */
and then store the Unix timestamp in the database.
Upon 'amdin_init' you'll need to do the exact opposite to load the date in the right format in the metabox:
global $post;
$custom = get_post_custom($post->ID);
if ($custom["date_field"][0]) {
$d = date("d/m/Y",$custom["date_field"][0]); // convert unix timestamp
} else {
$d = "";
}
And in your template file, use php functions setlocale and strftime to display the date:
$custom = get_post_custom($post->ID);
$d = $custom["date_field"][0];
setlocale(LC_TIME, 'nl_NL');
$s = strftime('%#d %B %Y',$s);
This should output something like 13 January 2012.
I have a DateTime object which I'm currently formating via
$mytime->format("D d.m.Y")
Which gives me exactly the format I need:
Tue 5.3.2012
The only missing point is the correct language. I need German translation of Tue (Tuesday), which is Die (Dienstag).
This gives me the right locale setting
Locale::getDefault()
But I don't know how to tell DateTime::format to use it.
Isn't there a way to do something like:
$mytime->format("D d.m.Y", \Locale::getDefault());
You can use the Intl extension to format the date. It will format dates/times according to the chosen locale, or you can override that with IntlDateFormatter::setPattern().
A quicky example of using a custom pattern, for your desired output format, might look like.
$dt = new DateTime;
$formatter = new IntlDateFormatter('de_DE', IntlDateFormatter::SHORT, IntlDateFormatter::SHORT);
$formatter->setPattern('E d.M.yyyy');
echo $formatter->format($dt);
Which outputs the following (for today, at least).
Di. 4.6.2013
That's because format does not pay attention to locale. You should use strftime instead.
For example:
setlocale(LC_TIME, "de_DE"); //only necessary if the locale isn't already set
$formatted_time = strftime("%a %e.%l.%Y", $mytime->getTimestamp())
IntlDateFormatter is the way to go currently (2023).
<?php
$formatter = new IntlDateFormatter(
$locale, // the locale to use, e.g. 'en_GB'
$dateFormat, // how the date should be formatted, e.g. IntlDateFormatter::FULL
$timeFormat, // how the time should be formatted, e.g. IntlDateFormatter::FULL
'Europe/Berlin' // the time should be returned in which timezone?
);
echo $formatter->format(time());
Will give a different output, depending on what you pass as $locale and the date and time format. I wanted to add some samples for future reference. Note that IntlDateFormatter::GREGORIAN and IntlDateFormatter::LONG are interchangable.
Locale: en_US
Format for Date & Time: Results in:
IntlDateFormatter::FULL Friday, August 5, 2022 at 3:26:37 PM Central European Summer Time
IntlDateFormatter::LONG August 5, 2022 at 3:26:37 PM GMT+2
IntlDateFormatter::MEDIUM Aug 5, 2022, 3:26:37 PM
IntlDateFormatter::SHORT 8/5/22, 3:26 PM
Locale: en_GB
Format for Date & Time: Results in:
IntlDateFormatter::FULL Friday, 5 August 2022 at 15:26:37 Central European Summer Time
IntlDateFormatter::LONG 5 August 2022 at 15:26:37 CEST
IntlDateFormatter::MEDIUM 5 Aug 2022, 15:26:37
IntlDateFormatter::SHORT 05/08/2022, 15:26
Locale: de_DE
Format for Date & Time: Results in:
IntlDateFormatter::FULL Freitag, 5. August 2022 um 15:26:37 Mitteleuropäische Sommerzeit
IntlDateFormatter::LONG 5. August 2022 um 15:26:37 MESZ
IntlDateFormatter::MEDIUM 05.08.2022, 15:26:37
IntlDateFormatter::SHORT 05.08.22, 15:26
Locale: fr_FR
Format for Date & Time: Results in:
IntlDateFormatter::FULL vendredi 5 août 2022 à 15:26:37 heure d’été d’Europe centrale
IntlDateFormatter::LONG 5 août 2022 à 15:26:37 UTC+2
IntlDateFormatter::MEDIUM 5 août 2022 à 15:26:37
IntlDateFormatter::SHORT 05/08/2022 15:26
As salathe has already said, you can also use $formatter->setPattern to further customize the output if needed.
While setlocale() is the correct answer and will still work but is outdated now.
strftime has been DEPRECATED as of PHP 8.1.0 Relying on this function is highly discouraged.
And mentioned Intl extension works perfectly, but not always handy.
One of the simplest ways to work with dates and times is to use Carbon2, CakePHP Chronos or similar library. It provides a single interface to all date's manipulations, formatting, and calculations. If you work with dates a lot I recommend using Carbon and then doing something like this
$date = Carbon::now()->locale('fr_FR');
echo $date->isoFormat('dd DD.MM.YYYY');
Please note that the format differs from the date() one. Full list see in Carbon docs but mentioned D d.m.Y can be something like dd DD.MM.YYYY.
If your project accepts 3rd party libraries, it's really the way to go. Also, if you're using the framework, please check, maybe Carbon (or its wrapper) is already included.
I made something that just does that, because there doesn't seem to exist a simple solution anywhere online, except for with strftime, which is very much deprecated!
My solution extends DateTime::format() with international month and day names and doesn't require installing a bunch of modules, learning new date formatting ways, etc.
After including the classes provided below you can use it as follows. Instead of
$date = new DateTime("2010-01-01 1:23");
echo $date->format("l (D) Y-M-d (F)");
Result: Friday (Fri) 2010-Jan-01 (January)
You can now use
$date = new DateTimeIntl("2010-01-01 1:23");
echo $date->format("l (D) Y-M-d (F)");
Result: vrijdag (vr) 2010-jan.-01 (januari) (Dutch locale).
You can dynamically change the $datetime->locale if wanted.
$date = new DateTimeIntl("2010-01-01 1:23");
$date->locale = "it_IT" ;
echo $date->format("l (D) Y-M-d (F)");
Result: venerdì (ven) 2010-gen-01 (gennaio)
Include this:
class DateTimePatternReplace {
function __construct(public string $DateTimeCode,
public string $IntDateFormatterCode,
public string $tempDateTimePlaceHolder) {}
}
trait addIntlDate {
public string $locale="nl_NL" ; // REPLACE BY YOUR FAVORITE LOCALE
private function getIntResult(string $pattern) {
if ( ! isset($this->formatter) || $this->formatter->getLocale(Locale::VALID_LOCALE) != $this->locale ) {
$this->formatter = new IntlDateFormatter($this->locale);
$this->locale = $this->formatter->getLocale(Locale::VALID_LOCALE); // store the valid version of the locale
}
this->formatter->setPattern($pattern);
return $this->formatter->format($this);
}
function format(string $pattern): string {
// The third parameter can NOT contain normal latin letters, these are random,
// distinctive codes not likely to be in a date format string
$replacePatterns = [/*weekdays*/new DateTimePatternReplace('l', 'EEEE', '[*ł*]'),
new DateTimePatternReplace('D', 'EEE', '[*Đ*]'),
/*month*/ new DateTimePatternReplace('F', 'MMMM', '[*ƒ*]'),
new DateTimePatternReplace('M', 'MMM', '[*μ*]'),
// add new replacements here if needed
] ;
$codesFound=[] ;
foreach($replacePatterns as $p) {
if ( str_contains($pattern, $p->DateTimeCode)) {
// replace codes not prepended by a backslash.
// known bug: codes prepended by double backslashes will not be translated. Whatever.
$pattern = preg_replace('/(?<!\\\)'.preg_quote($p->DateTimeCode)."/", $p->tempDateTimePlaceHolder, $pattern);
$codesFound[] = $p ;
}
}
$result = parent::format($pattern) ;
foreach($codesFound as $p) {
$code = $this->getIntResult($p->IntDateFormatterCode);
$result = str_replace($p->tempDateTimePlaceHolder, $code, $result);
}
return $result ;
}
}
// you can remove this str_contains addition in PHP 8 or higher
if (!function_exists('str_contains')) {
function str_contains($haystack, $needle) {
return $needle !== '' && mb_strpos($haystack, $needle) !== false;
}
}
// end str_contains addition
class DateTimeIntl extends DateTime {
use addIntlDate;
}
class DateTimeImmutableIntl extends DateTimeImmutable {
use addIntlDate;
}
This code extends DateTime and DateTimeImmutable, extends their normal formatting with a locale. So this keeps everything extremely simple
You can add new patterns to be translated if needed by adding codes to the array: a formatting pattern in DateTime::format()-syntax, a corresponding formatting pattern in IntlDateFormatter::format-syntax, plus a placeholder to be used in DateTime::format that does NOT contains letters/codes/patterns that will be used/replaced by the DateTime::format method. See as example the current four codes that use no letters in ASCII lower than 128 letters. (They do use Polish, Greek, Dutch and Slovak letters just for fun.)
Built and tested in PHP 8.1.
For some older version of PHP you will have to change the first class to
class DateTimePatternReplace {
public string $DateTimeCode;
public string $IntDateFormatterCode;
public string $tempDateTimePlaceHolder;
function __construct(string $DateTimeCode, string $IntDateFormatterCode, string $tempDateTimePlaceHolder) {
$this->DateTimeCode = $DateTimeCode;
$this->IntDateFormatterCode = $IntDateFormatterCode;
$this->tempDateTimePlaceHolder = $tempDateTimePlaceHolder;
}
}
This is how I solved combining the features of DateTime and strftime().
The first allows us to manage strings with a weird date format, for example "Ymd" (stored in db from a datepicker).
The second allows us to translate a date string in some language.
For example we start from a value "20201129", and we want end with an italian readable date, with the name of day and month, also the first letter uppercase: "Domenica 29 novembre 2020".
// for example we start from a variable like this
$yyyymmdd = '20201129';
// set the local time to italian
date_default_timezone_set('Europe/Rome');
setlocale(LC_ALL, 'it_IT.utf8');
// convert the variable $yyyymmdd to a real date with DateTime
$truedate = DateTime::createFromFormat('Ymd', $yyyymmdd);
// check if the result is a date (true) else do nothing
if($truedate){
// output the date using strftime
// note the value passed using format->('U'), it is a conversion to timestamp
echo ucfirst(strftime('%A %d %B %Y', $truedate->format('U')));
}
// final result: Domenica 29 novembre 2020