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.
Related
I need to loop dates, according to different $eventname. I was already able to write a script that adds one week to the original date, but I don't know how I can loop it for a defined time.
code used:
$eventname = $event->title;
// TODO: loop for specified times if $eventname contains definded strings
$start_date = helper('com://site/ohanah.date.format', array(
'date' => $event->start,
'format' => 'Y/m/d H:i',
'timezone' => 'UTC'
));
$date = strtotime($start_date) + 604800;
echo "<pre>";
echo date('d. F Y, H:i', $date);
echo ' - ';
echo helper('com://site/ohanah.date.format', array(
'date' => $event->end,
'format' => 'H:i',
'timezone' => 'UTC'
));
echo "</pre>";
Output: (start date would be one week before) 18. April 2018, 14:00 - 16:00
So my question is, how can I loop this that the output is e.g. 6 times with one week space between each of them?
When working with dates and times, do not add seconds to timestamps or something like that, because it will get you in trouble in leapyears and daylight saving times, because one day is not always 86400 seconds.
Better use PHP's DateTime and DateInterval classes.
<?php
$Date = new DateTime("2018-03-03 14:00:00");
for($i=0;$i<6;$i++) { //loop 6 times
$Date->add(new DateInterval('P1W')); //add one week
echo $Date->format("Y-m-d H:i:s").PHP_EOL;
}
Output:
2018-03-10 14:00:00
2018-03-17 14:00:00
2018-03-24 14:00:00
2018-03-31 14:00:00
2018-04-07 14:00:00
See also:
http://php.net/manual/en/class.datetime.php
http://php.net/manual/en/class.dateinterval.php
Something like that?
<?php
$oneWeek = 604800;
$date = '2018-04-05';
$dates = array($date);
for ($i = 0; $i < 6; $i++) {
$dates[] = $date = date('Y-m-d', strtotime($date) + $oneWeek);
}
var_dump($dates);
I am not entirely sure I understand the question, but it looks like you want to have a condition that will either set a specific number of times for the output loop or determine whether the loop is ran that number of times.
If so, you can set a counter variable with your condition, then run the loop that number of times, defaulting the counter variable to 1 in the case that you do not want to output more than one time:
$eventname = $event->title;
// TODO: loop for specified times if $eventname contains definded strings
$counter = (/*your condition for $eventname*/) ? 6 : 1;
for ($x = 0; $x < $counter; $x++) {
$start_date = helper('com://site/ohanah.date.format', array(
'date' => $event->start,
'format' => 'Y/m/d H:i',
'timezone' => 'UTC'
));
$date = strtotime($start_date) + 604800;
echo "<pre>";
echo date('d. F Y, H:i', $date);
echo ' - ';
echo helper('com://site/ohanah.date.format', array(
'date' => $event->end,
'format' => 'H:i',
'timezone' => 'UTC'
));
echo "</pre>";
}
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 have an offset from UTC stored in minutes: e.g -240
I'm trying to find the corresponding UNIX timestamp of midnight of the current day for this particular offset.
I found similar information in questions like this one: How do I get the UTC time of "midnight" for a given timezone?
However, I don't have the city name/timezone jurisdiction, just a minute offset. I think this should be fine since for my purposes I don't need to account for daylight savings, it can be off by an hour and still be fine.
Examples
Offset: -420
Midnight on 7/12/2014: 1405148400 (unix TS)
With UTC, I would have to first tell if it's the next day or same day as the TZ because it may have a different "last midnight".
While this solution looks a little ugly it does do what I think you're asking for! This example uses -180 minutes as the offset.
date_default_timezone_set('UTC');
// Work out which day the time zone is in
$day = strtotime('-180 minutes');
// Strip of the time part of the day, to give UTC midnight on the correct day
$utcMidnight = strtotime('midnight', $day);
// Now apply the offset in reverse to give the zone's midnight
$zoneMidnight = strtotime('+180 minutes', $utcMidnight);
You could use date_default_timezone_set to make all time-related functions acknowledge the shift. First thing to do is to convert those minutes into hours, since the UTC gap is 1 hour between n and n+1.
$hours = $minutes / 60;
I would also recommend that you check the minutes values first :
if($minutes % 60 == 0) // We're good.
Now, if you want to convert the UTC offset to a timezone, you can create your function :
<?php
function offsetToTimezone($offset){
$timezones = array(
"-12" => "Pacific/Kwajalein",
"-11" => "Pacific/Samoa",
"-10" => "Pacific/Honolulu",
"-9" => "America/Juneau",
"-8" => "America/Los_Angeles",
"-7" => "America/Denver",
"-6" => "America/Mexico_City",
"-5" => "America/New_York",
"-4" => "America/Caracas",
"-3.5" => "America/St_Johns",
"-3" => "America/Argentina/Buenos_Aires",
"-2" => "Atlantic/Azores",
"-1" => "Atlantic/Azores",
"0" => "Europe/London",
"1" => "Europe/Paris",
"2" => "Europe/Helsinki",
"3" => "Europe/Moscow",
"3.5" => "Asia/Tehran",
"4" => "Asia/Baku",
"4.5" => "Asia/Kabul",
"5" => "Asia/Karachi",
"5.5" => "Asia/Calcutta",
"6" => "Asia/Colombo",
"7" => "Asia/Bangkok",
"8" => "Asia/Singapore",
"9" => "Asia/Tokyo",
"9.5" => "Australia/Darwin",
"10" => "Pacific/Guam",
"11" => "Asia/Magadan",
"12" => "Asia/Kamchatka"
);
return $timezones[$offset];
}
?>
... and use if for conversion :
date_default_timezone_set(offsetToTimezone($hours));
By the way, I suggest you have a look at this answer, which provides you with a more elegant way to achieve the work of offsetToTimezone.
Now that your script if configured on the correct timezone, just ask for a timestamp :
$timestamp = mktime(0, 0, 0);
If at some time, you need to reset to timezone to default, you might need date_default_timezone_get to save it :
$timezone = date_default_timezone_get();
// Change to another timezone based on your offset.
// Get your timestamp.
date_default_timezone_set($timezone);
I had to think through it quite a bit, but I think this was the solution I was looking for. Let me know if you think this algorithm is incorrect.
function getLastMidnightForOffset( $minuteOffset ) {
$today = mktime( 0, 0, 0 );
$tomorrow = $today + 86400;
$yesterday = $today - 86400;
$offset = $minuteOffset * 60;
if ( time() + $offset >= $tomorrow ) {
$localMidnight = $tomorrow - $offset;
} elseif ( time() + $offset >= $today ) {
$localMidnight = $today - $offset;
} else {
$localMidnight = $yesterday - $offset;
}
return $localMidnight;
}
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;