Related
When upgrading to PHP 8.1, I got an error regarding "strftime".
How do I correct the code to correctly display the full month name in any language?
$date = strftime("%e %B %Y", strtotime('2010-01-08'))
To my dear and late strftime()... I found a way to adapt with IntlDateFormatter::formatObject and here is the link for the references to the schemas:
https://unicode-org.github.io/icu/userguide/format_parse/datetime/#date-field-symbol-table
... For those who want to format the date more precisely
// "date_default_timezone_set" may be required by your server
date_default_timezone_set( 'Europe/Paris' );
// make a DateTime object
// the "now" parameter is for get the current date,
// but that work with a date recived from a database
// ex. replace "now" by '2022-04-04 05:05:05'
$dateTimeObj = new DateTime('now', new DateTimeZone('Europe/Paris'));
// format the date according to your preferences
// the 3 params are [ DateTime object, ICU date scheme, string locale ]
$dateFormatted =
IntlDateFormatter::formatObject(
$dateTimeObj,
'eee d MMMM y à HH:mm',
'fr'
);
// test :
echo ucwords($dateFormatted);
// output : Jeu. 7 Avril 2022 à 04:56
I've chosen to use php81_bc/strftime composer package as a replacement.
Here the documentation.
Pay attention that the output could be different from native strftime 'cause php81_bc/strftime uses a different library for locale aware formatting (ICU).
Note that output can be slightly different between libc sprintf and this function as it is using ICU.
You can use the IntlDateFormatter class. The class works independently of the locales settings. With a function like this
function formatLanguage(DateTime $dt,string $format,string $language = 'en') : string {
$curTz = $dt->getTimezone();
if($curTz->getName() === 'Z'){
//INTL don't know Z
$curTz = new DateTimeZone('UTC');
}
$formatPattern = strtr($format,array(
'D' => '{#1}',
'l' => '{#2}',
'M' => '{#3}',
'F' => '{#4}',
));
$strDate = $dt->format($formatPattern);
$regEx = '~\{#\d\}~';
while(preg_match($regEx,$strDate,$match)) {
$IntlFormat = strtr($match[0],array(
'{#1}' => 'E',
'{#2}' => 'EEEE',
'{#3}' => 'MMM',
'{#4}' => 'MMMM',
));
$fmt = datefmt_create( $language ,IntlDateFormatter::FULL, IntlDateFormatter::FULL,
$curTz, IntlDateFormatter::GREGORIAN, $IntlFormat);
$replace = $fmt ? datefmt_format( $fmt ,$dt) : "???";
$strDate = str_replace($match[0], $replace, $strDate);
}
return $strDate;
}
you can use format parameters like for datetime.
$dt = date_create('2022-01-31');
echo formatLanguage($dt, 'd F Y','pl'); //31 stycznia 2022
There are extension classes for DateTime that have such functions integrated as methods.
echo dt::create('2022-01-31')->formatL('d F Y','pl');
The strftime is obsolete and DateTime::format() provide a quick replacement and IntlDateFormatter::format() provied a more sophisticated slution.
this links will be help you:
https://github.com/modxcms/revolution/issues/15864
https://github.com/php/php-src/blob/1cf4fb739f7a4fa8404a4c0958f13d04eae519d4/UPGRADING#L379-L381
https://www.php.net/manual/en/datetime.format.php
strftime is deprecated PHP 8.1, You can use date function.
$date = date("%e F Y", strtotime('2010-01-08'))
Hey I have also experienced this issue as well so after some research on PHP's official documentation here what I found!
https://www.php.net/manual/en/function.strftime.php
They are saying that it is depricated and use setlocale() function
this also work same as strftime().
For more information please visit official PHP docs of setlocale() https://www.php.net/manual/en/function.setlocale.php
A quick and simple replacement for the deprecated function strftime can be following.
Instead of using (taking the sample from the question)
$date = strftime("%e %B %Y", strtotime('2010-01-08'))
convert that to:
$date = date('d M Y', strtotime('2010-01-08')
So I've checked the list of supported time zones in PHP and I was wondering how could I include them in the date() function?
Thanks!
I don't want a default timezone, each user has their timezone stored in the database, I take that timezone of the user and use it. How? I know how to take it from the database, not how to use it, though.
For such task, you should really be using PHP's DateTime class. Please ignore all of the answers advising you to use date() or date_set_time_zone, it's simply bad and outdated.
I'll use pseudocode to demonstrate, so try to adjust the code to suit your needs.
Assuming that variable $tz contains string name of a valid time zone and variable $timestamp contains the timestamp you wish to format according to time zone, the code would look like this:
$tz = 'Europe/London';
$timestamp = time();
$dt = new DateTime("now", new DateTimeZone($tz)); //first argument "must" be a string
$dt->setTimestamp($timestamp); //adjust the object to correct timestamp
echo $dt->format('d.m.Y, H:i:s');
DateTime class is powerful, and to grasp all of its capabilities - you should devote some of your time reading about it at php.net. To answer your question fully - yes, you can adjust the time zone parameter dynamically (on each iteration while reading from db, you can create a new DateTimeZone() object).
If I understood correct,You need to set time zone first like:
date_default_timezone_set('UTC');
And than you can use date function:
// Prints something like: Monday 8th of August 2005 03:12:46 PM
echo date('l jS \of F Y h:i:s A');
The answer above caused me to jump through some hoops/gotchas, so just posting the cleaner code that worked for me:
$dt = new DateTime();
$dt->setTimezone(new DateTimeZone('America/New_York'));
$dt->setTimestamp(123456789);
echo $dt->format('F j, Y # G:i');
Use the DateTime class instead, as it supports timezones. The DateTime equivalent of date() is DateTime::format.
An extremely helpful wrapper for DateTime is Carbon - definitely give it a look.
You'll want to store in the database as UTC and convert on the application level.
It should like this:
date_default_timezone_set('America/New_York');
U can just add, timezone difference to unix timestamp.
Example for Moscow (UTC+3)
echo date('d.m.Y H:i:s', time() + 3 * 60 * 60);
Try this. You can pass either unix timestamp, or datetime string
public static function convertToTimezone($timestamp, $fromTimezone, $toTimezone, $format='Y-m-d H:i:s')
{
$datetime = is_numeric($timestamp) ?
DateTime::createFromFormat ('U' , $timestamp, new DateTimeZone($fromTimezone)) :
new DateTime($timestamp, new DateTimeZone($fromTimezone));
$datetime->setTimezone(new DateTimeZone($toTimezone));
return $datetime->format($format);
}
this works perfectly in 2019:
date('Y-m-d H:i:s',strtotime($date. ' '.$timezone));
I have created this very straightforward function, and it works like a charm:
function ts2time($timestamp,$timezone){ /* input: 1518404518,America/Los_Angeles */
$date = new DateTime(date("d F Y H:i:s",$timestamp));
$date->setTimezone(new DateTimeZone($timezone));
$rt=$date->format('M d, Y h:i:s a'); /* output: Feb 11, 2018 7:01:58 pm */
return $rt;
}
I have tried the answers based on the DateTime class. While they are working, I found a much simpler solution that makes a DateTime object timezone aware at the time of creation.
$dt = new DateTime("now", new DateTimeZone('Asia/Jakarta'));
echo $dt->format("Y-m-d H:i:s");
This returns the current local time in Jakarta, Indonesia.
Not mentioned above. You could also crate a DateTime object by providing a timestamp as string in the constructor with a leading # sign.
$dt = new DateTime('#123456789');
$dt->setTimezone(new DateTimeZone('America/New_York'));
echo $dt->format('F j, Y - G:i');
See the documentation about compound formats:
https://www.php.net/manual/en/datetime.formats.compound.php
Based on other answers I built a one-liner, where I suppose you need current date time. It's easy to adjust if you need a different timestamp.
$dt = (new DateTime("now", new DateTimeZone('Europe/Rome')))->format('d-m-Y_His');
If you use Team EJ's answer, using T in the format string for DateTime will display a three-letter abbreviation, but you can get the long name of the timezone like this:
$date = new DateTime('2/3/2022 02:11:17');
$date->setTimezone(new DateTimeZone('America/Chicago'));
echo "\n" . $date->format('Y-m-d h:i:s T');
/* Displays 2022-02-03 02:11:17 CST "; */
$t = $date->getTimezone();
echo "\nTimezone: " . $t->getName();
/* Displays Timezone: America/Chicago */
$now = new DateTime();
$now->format('d-m-Y H:i:s T')
Will output:
29-12-2021 12:38:15 UTC
I had a weird problem on a hosting. The timezone was set correctly, when I checked it with the following code.
echo ini_get('date.timezone');
However, the time it returned was UTC.
The solution was using the following code since the timezone was set correctly in the PHP configuration.
date_default_timezone_set(ini_get('date.timezone'));
You can replace database value in date_default_timezone_set function,
date_default_timezone_set(SOME_PHP_VARIABLE);
but just needs to take care of exact values relevant to the timezones.
I'm trying with:
setlocale(LC_ALL,"es_ES");
$string = "24/11/2014";
$date = DateTime::createFromFormat("d/m/Y", $string);
echo $date->format("l");
And I'm getting Monday, which is correct but I need it in spanish, so, is there any way to retrieve this day in spanish?
From the DateTime format page:
This method does not use locales. All output is in English.
If you need locales look into strftime
Example:
setlocale(LC_ALL,"es_ES");
$string = "24/11/2014";
$date = DateTime::createFromFormat("d/m/Y", $string);
echo strftime("%A",$date->getTimestamp());
I use:
setlocale(LC_ALL, "es_ES", 'Spanish_Spain', 'Spanish');
echo iconv('ISO-8859-2', 'UTF-8', strftime("%A, %d de %B de %Y", strtotime($row['date'])));
or
setlocale(LC_ALL,"es_ES#euro","es_ES","esp");
both works. I have to use iconv to avoid strange symbols in accents, and i obtain this result:
domingo, 09 de octubre de 2016
You can use strftime function:
setlocale( LC_ALL,"es_ES#euro","es_ES","esp" );
echo strftime( "%A %d de %B del %Y" );
or
function SpanishDate($FechaStamp)
{
$ano = date('Y',$FechaStamp);
$mes = date('n',$FechaStamp);
$dia = date('d',$FechaStamp);
$diasemana = date('w',$FechaStamp);
$diassemanaN= array("Domingo","Lunes","Martes","Miércoles",
"Jueves","Viernes","Sábado");
$mesesN=array(1=>"Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio",
"Agosto","Septiembre","Octubre","Noviembre","Diciembre");
return $diassemanaN[$diasemana].", $dia de ". $mesesN[$mes] ." de $ano";
}
This is how I did it.
// Define key-value array
$days_dias = array(
'Monday'=>'Lunes',
'Tuesday'=>'Martes',
'Wednesday'=>'Miércoles',
'Thursday'=>'Jueves',
'Friday'=>'Viernes',
'Saturday'=>'Sábado',
'Sunday'=>'Domingo'
);
//lookup dia based on day name
$dia = $days_dias[date('l', strtotime("1993-04-28"))];
strftime has been DEPRECATED as of PHP 8.1.0
Another alternative is using IntlDateFormatter:
$formatter = new \IntlDateFormatter(
'es_ES',
\IntlDateFormatter::LONG,
\IntlDateFormatter::LONG,
'Europe/Madrid' //more in: https://www.php.net/manual/en/timezones.europe.php
);
echo $formatter->formatObject(new \DateTime(), "eeee", "es_ES");
note that "eeee" is a format from ICU
Digging a bit on how to do this, most of the times people use the function strftime.
Unfortunately, the strftime function has been DEPRECATED as of PHP 8.1.0 and 'is highly discouraged' to rely on it.
You have two options:
Use the IntlDateFormatter function, but you need to install the intl extension for php and enable it in your php.ini file. This can be problematic in some shared production environments. The good side is you keep the output masks and if you use other languages you can easily exchange between them.
The code would be like this:
$d = new IntlDateFormatter('es_ES', null, null, null, null, null, 'dd MMMM y');
print($d->format(new DateTime('2022-12-01'));
and the output would be like this 01 Diciembre 2022
Use a handmade function so you can reuse it several times. It is easier and faster to use, but you lose output masks and is tied to a single language.
The code would be like this:
function fechaEspanol($fecha)
{
$format = 'Y-m-d H:i:s'; //This is an optional input format mask for datetime database extracted info
$d = DateTime::createFromFormat($format, $fecha); //A simple $d = new DateTime($fecha) can also be used
$anio = $d->format('Y');
$mes = $d->format('n');
$dia = $d->format('d');
$diasemana = $d->format('w');
$diassemanaN = array("Domingo", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado");
$mesesN = array(1 => "Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre");
return "{$diassemanaN[$diasemana]}, $dia de {$mesesN[$mes]} de $anio";
}
If fechaEspanol('2022-12-01 12:00:00') the output would be like this 01 Diciembre 2022. This function can be optimized, but is put like this for a clearer view of what is being done.
I hope this helps someone.
I have this part of the function, which gives me name of the months in English. How can I translate them to my local language (Serbian)?
$month_name = date('F', mktime(0, 0, 0, $i));
Where $i is the number of the month (values 1 - 12). See also PHP:mktime.
You should use setlocale():
setlocale(LC_TIME, 'fr_FR');
$month_name = date('F', mktime(0, 0, 0, $i));
In this case it would set it to French. For your case it should be one of the following:
sr_BA - Serbian (Montenegro)
sr_CS - Serbian (Serbia)
sr_ME - Serbian (Serbia and Montenegro)
You should use setlocale() and strftime():
setlocale(LC_TIME, 'sr_CS');
$month_name = strftime('%B', mktime(0, 0, 0, $i));
Here is an example with IntlDateFormatter
$format = new IntlDateFormatter('sr_CS', IntlDateFormatter::NONE,
IntlDateFormatter::NONE, NULL, NULL, "MMM");
$monthName = datefmt_format($format, mktime(0, 0, 0, $i));
For all who struggle with German (and de_DE), make sure you are using the right language code. Login to your server and run locale -a to see a list of all available ones. For me it shows:
CC.UTF-8de_AT.utf8de_BE.utf8de_CH.utf8de_DE.utf8de_LI.utf8de_LU.utf8...
You need to use one of those codes.
Then you can use:
date_default_timezone_set('Europe/Berlin');
setlocale(LC_ALL, 'de_DE.utf8');
$date_now = date('Y-m-d');
$month_available = strftime('%B %Y', strtotime($date_now));
$month_next = strftime('%B %Y', strtotime($date_now.' +1 month'));
and "März 2020" etc. get displayed correctly.
This question asks how to get a list of months, I only see hints, not a complete code answer so:
If you have IntlDateFormatter available - which is available in most of the cases, you can create a formatter in a given locale and repeatedly push a date to it created just based on month number
// or any other locales like pl_PL, cs_CZ, fr_FR, zh, zh_Hans, ...
$locale = 'en_GB';
$dateFormatter = new IntlDateFormatter(
$locale,
IntlDateFormatter::LONG, // date type
IntlDateFormatter::NONE // time type
);
$dateFormatter->setPattern('LLLL'); // full month name with NO DECLENSION ;-)
$months_locale = [];
for ($month_number = 1; $month_number <= 12; ++$month_number) {
$months_locale[] = $dateFormatter->format(
// 'n' => month number with no leading zeros
DateTime::createFromFormat('n', (string)$month_number)
);
}
// test output
echo "<pre>";
var_dump($months_locale);
echo "</pre>";
Note: LLLL takes care of not-declining, but it does not take care of the lowercase/uppercase of the first letter if the languages has such things.Good example is that you can get January for en_GB but leden for cs_CZ
If you want all letters lowercase => use mb_strtolower($month_name); - docs
If you want just the FIRST letter to be upper case =>
=> use mb_convert_case($month_name, MB_CASE_TITLE, 'UTF-8'); - docs
Always use mb_* functions or their variations for locale-originating strings !
So no, don't use ucfirst !
It is good idea to pass the encoding when setting the locale:
<?php
date_default_timezone_set('Europe/Belgrade');
setlocale(LC_TIME, array('sr_CS.UTF-8', 'sr.UTF-8'));
I have tried using date("m/d/Y", strtotime("04-05-2012")) but I will get "05/04/2012" or on some other dates for example "03-30-2012" I will get "12/31/1969" (which makes sense because it it mixing up the month and day and there is no 30th month. So how should I do this? I also want to then convert the value into a UNIX time so that I can search it against MySQL db.
You can use the DateTime object and createFromFormat static method to do it :
$date = DateTime::createFromFormat('m-d-Y',"03-30-2012");
$date->format('m/d/Y');
If you know for certain that the format you start with is DD-MM-YYY when why not use a simple replace?
e.g. $newDate = str_replace('-', '/', '04-05-2012');
One way to do it would be using explode() and mktime():
$inDate = '03-30-2012';
list($m, $d, $y) = explode('-', $inDate);
$outDate = date('m/d/Y', mktime(0, 0, 0, $m, $d, $y));
This assumes the format is somehow dynamic, though. Otherwise, str_replace() is your best option, as others pointed out.
This isn't so much a date format question as a string manipulation question.
But it's still good to know that strtotime() exists.
[ghoti#pc ~]$ cat transdate.php
#!/usr/local/bin/php
<?php
$olddate = "04-05-2012"; // assuming mm-dd-YYYY
// Get the date parts into an array
$parts = explode("-", $olddate);
// Switch to YYYY-mm-dd, which will be interpreted consistently
$neworder = sprintf("%s-%s-%s", $parts[2], $parts[0], $parts[1]);
printf("New order: %s\n", $neworder);
// Set your timezone, or PHP will whine and complain
date_default_timezone_set('America/Toronto');
// Convert your reordered date to an epoch second (unix timestamp)
$epoch = strtotime($neworder);
// At a terminal, `man strftime` (or read the PHP function's docs) for details.
print "Alternate formats:\n";
printf("\t%s\n", strftime("%D", $epoch));
printf("\t%s\n", strftime("%F", $epoch));
printf("\t%s\n", strftime("%A %B %e, %Y (week %U)", $epoch));
[ghoti#pc ~]$ ./transdate.php
New order: 2012-04-05
Alternate formats:
04/05/12
2012-04-05
Thursday April 5, 2012 (week 14)
[ghoti#pc ~]$
This will work in PHP 5.1.6. Heck, it should work in PHP 4, except for date_default_timezone_set().