Hi #ll and greetings from Germany,
Perhaps I am too blind to see, but I am struggling with a localisation problem. I hope that someone has a solution for that.
In a function I have a german date string, assume it's today:
$datestring = '3. März 2014'
Second, i have the date format used in WP
$date_format = get_option( 'date_format' );
What I am trying to achive is to get a valid unix timestamp from $datestring.
I tried several different approaches like strtotime, date_parse_from_format, etc., I even tried to set the locale environment via setlocale. Of course it would be easy to parse the string against an array with the month names and get an english datestring, but I want to have this ready for all languages.
Any Idea how to get this done? Help is really appreciated.
You need to use mktime($datestring)
and set the $datestring variable in accordance to:
http://pl1.php.net/manual/de/function.mktime.php
in wordpress:
mktime(get_the_date("H"), get_the_date("i"), get_the_date("s"), get_the_date("n"), get_the_date("j"), get_the_date("Y"));
if you need to convert exact format shown above:
$datestring = '3. März 2014';
$dateelements = explode(" ", $datestring);
$day = rtrim($dateelements[0], ".");
$germanMonths = array(1 => "Januar", 2 => "Februar", 3 => "März", 4 => "April", 5 => "Mai", 6 => "Juni", 7 => "Juli", 8 => "August", 9 => "September", 10 => "Oktober " , 11 => "November", 12 => "Dezember");
$month = array_search($dateelements[1], $germanMonths);
$year = $dateelements[2];
$unixtimestamp = mktime(0,0,0,$month,$day,$year);
and if you have a date format in wp option, and $datestring is in that format:
$dateformat = get_option('date_format');
echo $dateformat;
$date = date_create_from_format($dateformat, $datestring);
$new_format = date_format($date, 'm,d,Y');
$unixtimestamp = mktime(0,0,0,$new_format);
echo $unixtimestamp;
Related
There is a date and time string in the format "2 листопада 2020, 21:00, п’ятниця"
I want to convert it to DateTime.
I tried converting.
setlocale(LC_ALL, 'uk_UA');
$t = '2 листопада 2020, 21:00, п’ятниця';
$date = date_create_from_format('j F Y, H:i, l', $t);
If the language is English, the date is converted, if Ukrainian does not work. How to set the language for conversion.
I think the setLocale settings don't affect the functionality of the DateTime class. This class requires names in English. One simple way to solve the problem is to translate the month names and ignore the day name. If ignore the Day Name an incorrect name as in the example cannot generate an error.
$t = '2 листопада 2020, 21:00, п’ятниця';
$trans = [
'січня' => "January",
'лютого' => "February",
'березня' => "March",
'квітня' => "April",
'травня' => "May",
'червня' => "June",
'липня' => "July",
'серпня' => "August",
'вересня' => "September",
'жовтня' => "October",
'листопада' => "November",
'грудня' => "December",
];
$inputEn = strtr($t, $trans);
$date = date_create_from_format('j F Y, H:i, *', $inputEn);
var_dump($date);
//object(DateTime)#1 (3) { ["date"]=> string(26) "2020-11-02 21:00:00.000000" ...
This solution works independently of the setlocale settings.
The algorithm shown above is built into a PHP extension called dt for the DateTime API. You can find it here.
Using with this class is very easy:
$t = '2 листопада 2020, 21:00, п’ятниця';
$ok = dt::setDefaultLanguage('uk_UA');
$dt = dt::createDtFromFormat('j F Y, H:i, *', $t);
echo $dt; //2020-11-02 21:00:00
I have the following Dutch string date:
dinsdag, 18 april 2017
Now I want to strip the day and the month, and I can do that with the following example, but that doesn't work because its in Dutch and strtotime only works with English strings.
$stripDay = date('d',strtotime($date));
$stripMonth = date('m',strtotime($date));
So I checked for other options, and I found strptime function which states that it can work.
$format = '%l, %d %m %Y';
setlocale(LC_TIME, 'NL_nl');
setlocale(LC_ALL, 'nl_NL');
First I configured the format, and then I set the Locale. But if I use the following code it still gives me 1's back.
$stripDay = date('d',strptime($date));
$stripMonth = date('m',strptime($date));
Can someone explain to me what I am doing wrong here?
you can define array which contain english days and dutch day and then you can replace dutch string with english string like this:
<?php
function dutch_strtotime($datetime) {
$days = array(
"maandag" => "Monday",
"dinsdag" => "Tuesday",
"woensdag" => "Wednesday",
"donderdag" => "Thursday",
"vrijdag" => "Friday",
"zaterdag" => "Saturday",
"zondag" => "Sunday"
);
$months = array(
"januari" => "January",
"februari" => "February",
"maart" => "March",
"april" => "April",
"mei" => "May",
"juni" => "June",
"juli" => "July",
"augustus" => "August",
"september" => "September",
"oktober" => "October",
"november" => "November",
"december" => "December"
);
$array = explode(" ", $datetime);
$array[0] = $days[strtolower($array[0])];
$array[2] = $months[strtolower($array[2])];
return strtotime(implode(" ", $array));
}
$date = "woensdag 22 oktober 2014 08:41:42";
echo date("l d-m-Y H:i:s", dutch_strtotime($date)) . "<br />";
echo date("d-m-Y", dutch_strtotime($date));
?>
If you're running PHP with Intl you can use the IntlDateFormatter class rather than rolling your own translations:
$df = IntlDateFormatter::create(
'nl_NL',
IntlDateFormatter::FULL,
IntlDateFormatter::FULL,
'Europe/Amsterdam',
IntlDateFormatter::GREGORIAN,
'eeee, d MMMM yyyy'
);
// since the time is omitted from the string
// it uses 00:00 - which meant the timestamp
// was an hour off for me in the UK so it
// was rolling the date back to 23:00 the
// previous day. Forcing UTC sorts this.
$df->setTimeZone('Etc/UTC');
// outputs '2017-04-18'
echo date('Y-m-d', $df->parse('dinsdag, 18 april 2017'));
You'll probably need the ICU date format guide handy though as it's different to normal PHP date formatting (hence 'eeee' for the day).
I've got bunch of birthdays which are stored in format DDMMMYY. I need to convert those to date values, so i can store those in database.
Is there any easy way of telling strtotime function that date must be in the past?
<?php
$datestring = '22SEP41';
echo date('Y-m-d',strtotime($datestring)); //outputs 2041-09-22, should be 1941-09-22
?>
<?php
$datestring = '22SEP41';
$matches = [];
preg_match('/([0-9]{2})([A-Z]{3})([0-9]{2})/', $datestring, $matches);
$prefix = ($matches[3] <= date('y') ? '20' : '19');
$matches[3] = "{$prefix}{$matches[3]}";
$ts = strtotime("{$matches[1]} {$matches[2]} {$matches[3]}");
// date ('Y-m-d', $ts) == 1941-09-22
This assumes that 22SEP06 should be interpreted as 2006 rather than 1906 - basically it gives the output a range of 1917 -> 2016.
This method create a date of past century only if standard evaluated date is after today:
$date = date_create( $datestring );
if( $date->diff( date_create() )->invert )
{
$date->modify( '-100 years' );
}
echo $date->format( 'Y-m-d' );
For
$datestring = '22SEP41';
the output is:
1941-09-22
For
$datestring = '22SEP01';
the output is:
2001-09-22
eval.in demo
Basically, we create a DateTime based on given string, then we calculate difference with current day; if the difference is negative (->invert), we subtract 1 century from the date.
You can personalize the condition using ->format('%R%Y') instead of ->invert. In this example:
if( $date->diff( date_create() )->format('%R%Y') < 10 )
Dates from 00 through 05 as evaluated as 2000-2005.
You could try something like:
$ds = '22SEP41';
$day = $ds[0].$ds[1];
// Getting the month.
$mon = array(
'JAN' => 1,
'FEB' => 2,
'MAR' => 3,
'APR' => 4,
'MAY' => 5,
'JUN' => 6,
'JUL' => 7,
'AUG' => 8,
'SEP' => 9,
'OCT' => 10,
'NOV' => 11,
'DEC' => 12
);
$mont = $ds[2].$ds[3].$ds[4];
$month = $mon[$mont]; // Gets the month real.
$year = '19'.$ds[5].$ds[6];
$final = $day.'-'.$month.'-'.$year;
I tested it on my local machine and it worked. Hope it works and is what you're looking for :)
I'm using this code to retrieve news items from my MongoDB:
foreach (collection("news")->find(["created"=>$time]) as $news)
Now I would like to find only those news articles with "created" unix timestamp that matches specific month of the specific year, like April 2014.
Any help would be appreciated.
Cheers.
EDIT: Thank you all for your effort, and yes, it's unix timestamp.
How did you create the Unix Timestamp? How is it represented in the document?
Are you using the MongoDate type, or are you using an integer?
If you are using the MongoDate type then you need to construct MongoDate objects and use them for your $gte and $lt conditions
$article = array(
"title" => "My first article",
"content" => "This is good news",
"published" => new MongoDate(),
"author" => "Random guy on the internet",
);
$collection->insert($article);
$start = new MongoDate(strtotime("yesterday"));
$end = new MongoDate(strtotime("tomorrow"));
$cursor = $collection->find(array("ts" => array('$gt' => $start, '$lte' => $end)));
foreach($cursor as $article) {
var_dump($article);
}
See http://www.php.net/manual/en/class.mongodate.php for more info
you'll have build your own query:
SELECT * FROM news WHERE created >= $start_date AND created <= $end_date
where:
assuming created is unix timestamp, otherwise you should skip strtotime function
// first day of april 2014
$start_date = strtotime(date('2014-04-01'));
// last day of april 2014
$end_date = strtotime(date('2014-04-t'));
You could use DateTime::createFromFormat to create your timestamps.
$begin = DateTime::createFromFormat('!Y-m', '2014-04');
$end = clone $begin;
$end->modify('next month');
echo $begin->format('Y-m-d H:i:s'). PHP_EOL; // 2014-04-01 00:00:00
echo $end->format('Y-m-d H:i:s'); // 2014-05-01 00:00:00
And build more complex condition.
collection("news")
->find(["created" => array(
'$gte' => $begin->getTimestamp(),
'$lt' => $end->getTimestamp())]);
I'm trying to create a conditional translation of the PHP internal date() function. Is it possible to somehow redefine the internal variables - e.g. - date('M'), date('y') etc so that different strings are fed into the remainder of the PHP function on the basis of this test:
if (ICL_LANGUAGE_CODE == 'fr') { }
The following is a working example of the code I'm using for a dates module. Since $date is defined with many variables contained in this definition it's important to conditionally re-define the variables within PHP's date() first in order to avoid having to redefine the variable 100 times or more within each key.
if($start <= $end):
if($start == $end):
//Month Day, Year
$date = date('F', $start).' '.date('j',$start).', '.date('Y', $start);
else:
if($start_year == $end_year):
if($start_month == $end_month):
//Month Day - Day, Year
$date = date('F', $start).' '.date('j',$start).' - '.date('j', $end).', '.date('Y', $start);
else:
//Month Day - Month Day, Year
$date = date('F', $start).' '.date('j',$start).' - '.date('F', $end).' '.date('j', $end).', '.date('Y', $start);
endif;
else:
//Month Day, Year - Month Day, Year
$date = date('F', $start).' '.date('j',$start).', '.date('Y', $start).' - '.date('F', $end).' '.date('j', $end).', '.date('Y', $end);
endif;
endif;
endif;
Whenever you need to manipulate date/time stamps based on locale, you should use strftime:
switch ($lang) {
case 'en':
setlocale(LC_TIME, 'en_CA.UTF-8');
echo strftime("%B %e, %G");
break;
case 'fr':
setlocale(LC_TIME, 'fr_CA.UTF-8');
echo strftime("%e %B %G");
break;
}
Results:
February 11, 2011 // en
11 février 2011 // fr
Of course, you need to have the locales installed on your system. In Ubuntu per example:
bash-4.1$ sudo locale-gen fr_CA.UTF-8
EDIT in may 2022
strftime() has been DEPRECATED as of PHP 8.1.0
This is how you should do it:
$fmt = datefmt_create(
'pt_BR', // The output language.
\IntlDateFormatter::FULL,
\IntlDateFormatter::FULL,
pattern: "cccc, d 'de' LLLL 'de' YYYY" // The output formatting.
);
$input = strtotime('20-06-2022');
$output = datefmt_format($fmt, $input);
var_dump($output); // Outputs "segunda-feira, 20 de junho de 2022".
As for strtotime() use:
slash (/) for American M/D/Y formatting;
dash (-) for European D-M-Y formatting and
period (.) for ISO Y.M.D formatting.
In my sample I am using the european day-month-year formatting.
Click here to see how to format the value of $pattern parameter in datefmt_create().
You must have the intl package installed:
$ sudo apt install php8.1-intl
Change the 8.1 bit to the php version you are working with.
$date = date('F', $start).' '.date('j',$start).', '.date('Y', $start);
That's a rather painful way to go about. The format string in date() doesn't have to be a single character. This line could be reduced to
$date = date('F j Y');
And given that, you could have a simple
switch($whats_my_locale) {
case 'FR':
$format = 'date format characters for a french date';
break
case 'EN' :
$format = 'format chars for english date'
break
case etc....
default:
$format = 'default date format string here';
}
$local_date_string = date($format, $start);
and off you go.
I'm sure you have, but have you considered just using the numeric values?
Also, if you do use them, remember the US has months / day, opposite to the UK and others.
I was looking for this lately and I found out a way to translate datetime in php.
Let's take the fr example
First I created a new Class that extend GlobalDateTime
in App\Core\DateTime.php
namespace App\Core;
use DateTime as GlobalDateTime;
class DateTime extends GlobalDateTime
{
public function __construct($str_date = "now")
{
parent::__construct($str_date);
}
public function toLocalTimeString(): string
{
$Y = $this->format('Y');
$M = $this->_get('month', $this->format('m'));
$l = $this->_get('day', $this->format('l'));
$d = $this->format('d');
$H = $this->format('H');
$i = $this->format('i');
return "$l $d $M $Y à $H:$i";
}
private function _get($key, $id): string
{
return [
'day' => [
0 => "Dim",
1 => "Lun",
2 => "Mar",
3 => "Mer",
4 => "Jeu",
5 => "Ven",
6 => "Sam",
"Sun" => "Dim",
"Mon" => "Lun",
"Tue" => "Mar",
"Wed" => "Mer",
"Thu" => "Jeu",
"Fri" => "Ven",
"Sat" => "Sam",
"Sunday" => "Dimanche",
"Monday" => "Lundi",
"Tuesday" => "Mardi",
"Wednesday" => "Mercredi",
"Thursday" => "Jeudi",
"Friday" => "Vendredi",
"Saturday" => "Samedi",
],
'month' => [
"01" => "Jan",
"02" => "Fév",
"03" => "Mar",
"04" => "Avr",
"05" => "Mai",
"06" => "Juin",
"07" => "Juil",
"08" => "Aôut",
"09" => "Sept",
"10" => "Oct",
"11" => "Nov",
"12" => "Déc",
],
][$key][$id];
}
}
And then I can call it wherever I want like
use App\Core\DateTime;
$datetime = new DateTime('now');
$strdatetime = $datetime->toLocalTimeString(); // return vendredi 18 Aôut 2022 à 08:00
You can custom this DateTime class as you like
I hope this will help you.