This question already has answers here:
Create a new date from php array
(3 answers)
Closed 4 years ago.
For a project, i need to convert multiple values form an array to a time format in PHP. I've got arrays like this:
starttime = ['year' => 2019, 'month' => 5, 'day' => 10, 'hour' => 20, 'minute' => 15]
Is there a way to convert these values to a time format with which i can also calculate stuff? I already tried using strtotime, but it dind't work. Thanks for your answers!
I suggest using the DateTime object which has the setDate, setTime and getTimestamp methods. Which you can use for defining the date and time from the array keys, and retrieve the unix timestamp as a result.
Example: https://3v4l.org/o3lVr
$starttime = ['year' => 2019, 'month' => 5, 'day' => 10, 'hour' => 20, 'minute' => 15];
$date = new \DateTime();
$date->setDate($starttime['year'], $starttime['month'], $starttime['day']);
$date->setTime($starttime['hour'], $starttime['minute']);
var_dump($timestamp = $date->getTimestamp());
var_dump(date('Y-m-d H:i:s', $timestamp));
Results:
int(1557512100)
string(19) "2019-05-10 20:15:00"
Optionally to prevent issues with missing keys, in PHP >= 7.0 you can use the null coalesce operator ?? to default the values to the current date.
Example: https://3v4l.org/0MOI5
$starttime = ['month' => 5, 'day' => 10, 'minute' => 15];
$date = new \DateTime();
$date->setDate($starttime['year'] ?? $date->format('Y'), $starttime['month'] ?? $date->format('m'), $starttime['day'] ?? $date->format('d'));
$date->setTime($starttime['hour'] ?? $date->format('H'), $starttime['minute'] ?? $date->format('i'));
var_dump($timestamp = $date->getTimestamp());
var_dump(date('Y-m-d H:i:s', $timestamp));
Results:
int(1557497700)
string(19) "2019-05-10 16:15:00"
Alternatively you can also use mktime to produce the same result. Please note, as per the manual, in PHP < 5.1.0 this method may produce unexpected (but not incorrect) results if DST is not specified.
Example: https://3v4l.org/DU0Q1
$starttime = ['year' => 2019, 'month' => 5, 'day' => 10, 'hour' => 20, 'minute' => 15];
$timestamp = mktime(
$starttime['hour'],
$starttime['minute'],
0,
$starttime['month'],
$starttime['day'],
$starttime['year']
);
var_dump($timestamp);
var_dump(date('Y-m-d H:i:s', $timestamp));
Results:
int(1557512100)
string(19) "2019-05-10 20:15:00"
Related
I got a date with format 'Y-m-d', and want to get the day from it. Like if I have 2021.01.01, I want for example Friday, or Thursday depending on what day it actually is. I already got the date stored as $date and I want the day stored as $day.
I've already tried this, without any error, and without anything happening:
$day = Carbon::createFromFormat('Y-m-d', $date)->format('1');
var_dump($day);
I've found another solution for you :
$timestamp = strtotime('2009-10-22');
$day = date('l', $timestamp);
echo $days;
output:
Thursday
You can try this ,
$d=unixtojd(mktime(0,0,0,6,20,2007));
var_dump(cal_from_jd($d,CAL_GREGORIAN));
output :
array (size=9)
'date' => string '6/20/2007' (length=9)
'month' => int 6
'day' => int 20
'year' => int 2007
'dow' => int 3
'abbrevdayname' => string 'Wed' (length=3)
'dayname' => string 'Wednesday' (length=9)
'abbrevmonth' => string 'Jun' (length=3)
'monthname' => string 'June' (length=4)
And for your code , you just need to add your date like this
$d=unixtojd(mktime(0,0,0,month,days,year));
$calendar = cal_from_jd($d,CAL_GREGORIAN);
var_dump($calendar['dayname']);
It seems like you used a 1 (one) instead of an l (lowercase L). If you change that, it works fine.
$day = Carbon::createFromFormat('Y-m-d', $date)->format('l');
var_dump($day);
This works, you seem to be using 1 instead of l
$today = Carbon::now();
$dayName = $today->format('l');
When using Carbon, ->dayName is the obvious and more explicit way:
Carbon::createFromFormat('Y-m-d', $date)->dayName
It also allow you to have it in any language:
Carbon::createFromFormat('Y-m-d', $date)->locale('fr_FR')->dayName
I want to display the start date and end date of the week. I have One date and a string like 1W4 and,in 1W4 consider 4 weeks and 1 visit so, my string like this 2W4,1W2,3W3,1W1,2W4.
I want to make start date and end date of week array according to string and week start from Sunday to Saturday.
Please post me if anyone has solution.Please ignoring if mistake in asking Question.
Thank you.
Try my php code:
From php.net datetime.format:
W: ISO-8601 week number of year, weeks starting on Monday.
The first calendar week of a year is that one which includes the first Thursday of that year.
So I have to rest one day to the start week date.
I assumed that the weeks correspond to the current year.
Input string:
$weeksString = "2W4,1W2,3W3,1W1,2W4";
Code:
<?php
$weeksArray = explode(",", $weeksString);
$result = array();
foreach($weeksArray as $visitsWeek) {
list($visits, $week) = explode("W", $visitsWeek);
$startDate = date("Y-m-d", strtotime(date("Y") . "W" . str_pad($week, 2, "0", STR_PAD_LEFT) . " -1 days"));
$endDate = date("Y-m-d", strtotime($startDate . " +6 days"));
$result[] = array("week" => $week, "startDate" => $startDate, "endDate" => $endDate);
}
?>
Output array $result:
array ( 0 => array ( 'week' => '4', 'startDate' => '2021-01-24', 'endDate' => '2021-01-30', ), 1 => array ( 'week' => '2', 'startDate' => '2021-01-10', 'endDate' => '2021-01-16', ), 2 => array ( 'week' => '3', 'startDate' => '2021-01-17', 'endDate' => '2021-01-23', ), 3 => array ( 'week' => '1', 'startDate' => '2021-01-03', 'endDate' => '2021-01-09', ), 4 => array ( 'week' => '4', 'startDate' => '2021-01-24', 'endDate' => '2021-01-30', ), )
I'm trying to get the difference between two dates like this
[
'years' : 4, // 0 if the difference is not above a year
'months': 4, // 0 if the difference is not of above a month
'weeks': 4, // 0 if the difference is not of above a week
'days': 4, // 0 if the difference is not of above a day
'hours' : 4 // 0 if the difference is not of above a hour
'minutes': 54 // 0 if the difference is not of above a minute
'seconds': 5 // 0 if the difference is not of above a second
]
Is there any utility function that gives me an output something like above in laravel PHP
this is my code at the moment
$date1 = new Carbon('2018-08-18 11:09:12');
$date2 = new Carbon('2018-04-02 08:15:03');
// dd($date1->diffForHumans($date2, false, false, 6));
$p = $date2->diffForHumans($date1, false, false, 6);
You could use the diffAsCarbonInterval()
$p = $date2->diffAsCarbonInterval($date1);
Then you can access the above values with:
$p->years //year
$p->months //month
$p->weeks //week
$p->daysExcludeWeeks //day
$p->hours //hour
$p->minutes //minute
$p->seconds //second
Or to take it one step further you could create a macro. One way to do this would be to add the following to the register method of your app service provider:
\Carbon\Carbon::macro('diffAsArray', function ($date = null, $absolute = true) {
$interval = $this->diffAsCarbonInterval($date, $absolute);
return [
'year' => $interval->years,
'month' => $interval->months,
'week' => $interval->weeks,
'day' => $interval->daysExcludeWeeks,
'hour' => $interval->hours,
'minute' => $interval->minutes,
'second' => $interval->seconds,
];
});
Then you can call:
$p = $date2->diffAsArray($date1);
Obviously, feel free to change the method name of the macro to something else if you want to.
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 :)
>> $start_dt = new DateTime()
DateTime::__set_state(array(
'date' => '2012-04-11 08:34:01',
'timezone_type' => 3,
'timezone' => 'America/Los_Angeles',
))
>> $end_dt = new DateTime()
DateTime::__set_state(array(
'date' => '2012-04-11 08:34:06',
'timezone_type' => 3,
'timezone' => 'America/Los_Angeles',
))
>> $start_dt->setTimestamp(strtotime('31-Jan-2012'))
DateTime::__set_state(array(
'date' => '2012-01-31 00:00:00',
'timezone_type' => 3,
'timezone' => 'America/Los_Angeles',
))
>> $end_dt->setTimestamp(strtotime('1-Mar-2012'))
DateTime::__set_state(array(
'date' => '2012-03-01 00:00:00',
'timezone_type' => 3,
'timezone' => 'America/Los_Angeles',
))
>> $interval = $start_dt->diff($end_dt)
DateInterval::__set_state(array(
'y' => 0,
'm' => 0,
'd' => 30,
'h' => 0,
'i' => 0,
's' => 0,
'invert' => 0,
'days' => 30,
))
>> $interval->format('%mm %dd')
'0m 30d'
i.e., 31-Jan-2012 to 1-Mar-2012 yields less than a month! I'd expect the output to be 1 month, 1 day. It shouldn't matter the number of days in February; that's the point of using a time library -- it's supposed to handle these things. WolframAlpha agrees.
Should I file a bug to PHP? Is there a hack/fix/workaround to get months to work as expected?
Updated answer
This behavior of DateTime::diff is certainly unexpected, but it's not a bug. In a nutshell, diff returns years, months, days etc such that if you did
$end_ts = strtotime('+$y years +$m months +$d days' /* etc */, $start_ts);
you would get back the timestamp that corresponds to end original end date.
These additions are performed "blindly" and then date correction applies (e.g. Jan 31 + 1 month would be Feb 31, corrected to Mar 2 or Mar 3 depending on the year). In this specific example you cannot add even one month as salathe also explains.
Should I file a bug to PHP?
No.
The "month" part of the interval means that the month part of the start date can be incremented by that many months. The behaviour in PHP, taking your start date of 31-Jan-2012 and incrementing the month (literally, 31-Feb-2012) and then correcting for a valid date (PHP does this for you) would give 02-Mar-2012 which is later than the target date that you are working with.
To demonstrate this, take your start date and add n months for a few months to see the behaviour.
31-Jan-2012 (Interval)
02-Mar-2012 (P1M)
31-Mar-2012 (P2M)
01-May-2012 (P3M)
31-May-2012 (P4M)
01-Jul-2012 (P5M)
You can see that the month is being incremented, then adjusted to make a valid date.