I am constructing a diary that has weekly views which I thought I had cracked because the dates seemed to appears as correct. It wasn't until my MySQL queries kept returning what seemed like random results that I realized the the month is actually being seen as the day instead.
$week_number = date("W");
$year = date("Y");
for ($day=0; $day<=6; $day++) {
$daily_date = date('d/m/Y', strtotime($year."W".$week_number.$day))."\n";
$StartDate = date('d', strtotime($daily_date));
}
echo $starteDate;
$startDate returns the number of the month rather than the day and sure enough date('m', strtotime($daily_date)) returns the day rather than the month.
I can't understand where I have made this silly mistake so any help would be appreciated.
This is because of the Americanisation of dates - strtotime will read the date as m/d/Y rather than d/m/Y.
The ISO for dates is Y-m-d and for ease I would use this format when doing any kind of date manipulation.
That code is horrible. You're converting dates to strings multiple times. There is absolutely NO reason to take your $year . w. $week_number.etc... value, convert it to a string, then convert that string back to a date just to extract the day value.
As well, d/m/Y is a horrible format to use for date transport, because... riddle me this, what is 01/02/03. Is that 3rd Feb 2001? 1 Mar 2002? If you can't figure it out, how can you expect strtotime to be better at it? it's fairly smart, but it's not omnicient, and it's DEFINITELY not infallible. A 4digit year does make it a bit easier, but you can still end up with d/m v.s. m/d confusion.
Why not simply
$StartDate = date('d', strtotime($year."W".$week_number.$day));
or better yet, use the DateTime class and select an appropriate DateInterval
Related
I'm having problems comparing two dates in PHP. I want to compare the current date to one entered by a user.
$date = "18/05/2018";
The date input by the user.
$date_unix = strtotime($date);
Used to convert the date from the given format to time, in order to be compared.
if($date_unix < time()){
echo '<b>Notice:</b> You cannot specify a date in the past.<br>';
}
The above if statement is always run and i'm confused as to why. Any help would be appreciated.
strtotime makes assumptions about the date format, and in this case those assumptions are wrong.
You are using a day/month/year format (like me: that's the default format in Italy). Yesterday, a date of 12/05/2018 would have been taken by strtotime, and assumed to be december 5th, 2018. The test would have been passed, and apparently been correct.
And if it had been a reservation, it would have incurred in seven months' worth of charges ;-D
So always specify the format. For that, I feel that the best is using DateTime:
$date = date_create_from_format('d/m/Y', '18/05/2018');
for the same reasons, be wary how you calculate date differences.
(Also, be wary of Daylight Saving Time).
From the strtotime documentation:
Dates in the m/d/y or d-m-y formats are disambiguated by looking at the separator between the various components: if the separator is a slash (/), then the American m/d/y is assumed
As 18/05/2018 is not a valid date in the American format (where the first number represents the month), your strtotime call will return false. And false (zero) will always be less than time().
The simplest fix, if you are confident about the format of the input, would be to replace the slashes with dashes before converting to timestamp. strtotime will then interpret the string as an international date which will work correctly:
$date = str_replace('/', '-', "18/05/2018");
$date_unix = strtotime($date);
However, updating your code to use the DateTime class, as in smith or LSerni's answers, will probably give you more flexibility going forward.
should stop uing the legacy strtotime and start using the DateTime class
$date = "18/05/2018";
$newDate = DateTime::createFromFormat('d/m/Y', $date);
if (new DateTime() < $newDate) {
echo 'future';
}else{
echo 'past';
}
To fix this problem, using information provided above I used the explode() to split up the $date variable into an array then rearrange the resulting array. I then pieced the exploded variables back together to form the correct American date format.
Below is the code relating to the above description:
$splitdate = (explode("/",$date));
$splitdate_day = $splitdate[0];
$splitdate_month = $splitdate[1];
$splitdate_year = $splitdate[2];
$date_change = $splitdate_month . "/" . $splitdate_day . "/" . $splitdate_year;
if(strtotime($date_change) < time()){
echo '<b>Notice:</b> You cannot specify a date in the past.<br>';
}
This may not be the most efficent method, but it solved the issue I was encoutering.
Currently, I'm trying to parse out dates when messages were received into timestamps. I have the month and day but the year is not specified. The event always occurs at the most recent (human) reading of the time. It works great in most cases to do this:
$time = strtotime("Jan 2 8:38pm");
That returns a date for this year, which is correct. Unfortunately, I get problems when I try to do for example:
$time = strtotime("Dec 31 8:38pm");
That returns a date which hasn't happened yet, and wont happen for the whole rest of the year. Obviously, my message was not sent in the future. I need it to return December 31st of last year.
For weekdays, I had a solution by prepending 'last' before the weekday like so:
$time = strtotime("Last Saturday 8:38pm");
That always returned the time of the last Saturday. However, trying to do the same thing here doesn't work:
$time = strtotime("Last Dec 31 8:38pm");
This returns false. I know to decrement a date by 1 year, I can do this:
$time = strtotime("Dec 31 8:38pm -1 year");
And that works great for Dec 31. However, Jan 2 will now fail:
$time = strtotime("Jan 2 8:38pm -1 year");
One solution I thought of was to subtract off a year (86400 * 365) from the resulting value if it is past today's date. However, this result will fail if we passed over February of a leap year. In that case, we would end up with a time that was ahead by a day.
The best solution I came up with so far is this:
$time = strtotime($raw_time);
if ($time > time()) {
$time = strtotime($raw_time." -1 year");
}
It seems kind of wasteful to make two calls to strtotime which I know is probably not a very efficient function. Is this the most elegant solution?
Is anyone aware of an option in strtotime which forces the dates to be in the past instead of in the future?
Is there another way to parse these dates that I should consider?
Efficiency is important for this because I am going to be parsing a lot of dates with it, but I would also like simple and readable code so I can understand it later.
Your approach is fine, as there is no date format to get what you want. Another approach could be using the DateTime class:
$datetime = new DateTime($raw_time);
if ($datetime > new DateTime()) {
$datetime->modify('-1 year');
}
You could test which one of the two approaches is faster. My guess is that this is a micro-optimization that won't make a lot of difference.
Somebody please help me to format the date. I'm not familiar with date formatting.
I want to increment the date by one month but i get this error:
"A non well formed numeric value encountered"
$bseDate=$_POST['lastBseDate']; //this will return 2014-04-03
$nextBse = date('y-m-d', strtotime("+1 month", $bsedate));
Use Datetime() for all date manipulation as it takes Daylight Savings Time and more into consideration and is more readable and maintainable.
$nextBse = (new DateTime($_POST['lastBseDate']))->modify('+1 month')->format('y-m-d');
To answer your question, strtotime gives a timestamp from a string, but since you are providing the optional base time it needs to be a timestamp as well:
$nextBse = date('y-m-d', strtotime("+1 month", strtotime($bseDate)));
I'm displaying a due date for tasks in an m/d/y format. I'm displaying the day the task was posted in a "Posted X $name(s) ago" (eg. "Posted 6 day(s) ago").
I'm working on giving the timestamps (posted and due date) different CSS classes, depending on how many days there are from TODAY until the due date. (So the "Posted X" timestamp is less relevant, I just wanted to give a better picture.)
So far, I have the following down:
$cdate = $this->data['due'];
$today = time();
$dovi = date('m/d/Y', $today);
$difference = $cdate - $dovi;
$upcoming= floor($difference/60/60/24);
$cdate is pulling the due date from the DB, in m/d/y format. $today is telling us what today is (using the UNIX timestamp). $dovi is converting time() in to the m/d/y format. $difference is telling us the difference between today and the due date. $upcoming, in theory, should take that difference and dumb it down into a simple number.
I think that for the calculation to work, I would need to convert $cdate in to a UNIX timestamp or somehow convert both $today and $cdate into some other matching format other than m/d/y.
Does anyone have suggestions on the best way to make this work? I already have some code to run the CSS changes, the only thing I'm stuck on is this conversion/calculation issue to determine how many days from NOW (time()) the due date is. Thanks!!
Maybe something like this? Assuming $this->data['due'] is in m/d/Y format.
$this->data['due'] = '7/28/2012';
$diff = strtotime($this->data['due']) - strtotime(date('m/d/Y'));
var_dump(date('d',$diff)); // 3
You can pass any valid parameter to php's date function to have it formatted however you would like.
Its long one, but works...
$datetime = new DateTime("2012-07-22 02:03:50"); // your date in datetime type
$curr_stamp = time();
$act_stamp = mktime($datetime->format('H'), $datetime->format('i'), $datetime->format('s'), $datetime->format('n'), $datetime->format('j'), $datetime->format('Y'));
$diff=$curr_stamp-$act_stamp;
$day_diff = floor($diff / 86400);
if($day_diff < 7)
echo $day_diff." days ago";
Rather elegant and right solution (and also viable after the end of UNIX epoch).
$today = new DateTime(); // creating `today` DateTime object
$expiry = DateTime::createFromFormat('m/d/Y', $this->data['due']) // creating DateTime object from already formatted date
$difference = $today->diff($expiry); // 1st variant to calculate difference between dates
$difference = date_diff($today, $expiry); // and 2nd variant
echo $difference->format('Interval (difference) is %R% days');
Remember that UNIX epoch (timestamp) will "end" "soon" and code based on timestamps possibly will face some problems (maybe we will find the solution in future to avoid this, but ...), it is better to use DateTime class, bec. even to calculate number of years for those who are born before 1970 year can become kinda problem if you don't remember the date 1970.01.01 and trying to do it using timestamps (it is widespread database practice BTW :) ).
Never do it (timestamps) for very old dates and look to the future and DateTime will SaveOurSouls.
I have been looking online for this answer and have come up empty...I am extremely tired so I thought I would give this a go....
I have a variable that has a date from a textbox
$effectiveDate=$_REQUEST['effectiveDate'];
What I am trying to do is take this date and add the current time
date('Y-m-d H:i:s', strtotime($effectiveDate))
When I echo this out I get 1969-12-31 19:00:00
Is this possible? Can someone point me in the right direction?
I found a solution to my problem....
$currentDate = date("Y-m-d");
$currentTime = date("H:i:s");
$currentDate = date("Y-m-d H:i:s", strtotime($currentDate . $currentTime));
echo $currentDate;
This takes a date from variable in one format and takes the date from another variable in another format and puts them together :)
Thanks everyone for their time.....
DateTime::createFromFormat
would also work but only if you have PHP 5.3 or higher...(I think)
The effectiveDate string is not in a format that strtotime recognizes, so strtotime returns false which is interpreted as 0 which causes the date to be displayed as January 1, 1970 at 00:00:00, minus your time zone offset.
The result you see is caused by the entered date not being in a format recognised by strtotime. The most likely case I can think of without knowing the format you used is that you used the US order of putting the month and day the wrong way around - this confuses strtotime, because if it accepts both then it can't distinguish February 3rd and March 2nd, so it has to reject US-formatted dates.
The most reliable format for strtotime is YYYY-MM-DD HH:ii:ss, as it is unambigous.
The date is just a timestamp, it is not object-oriented and i don't like it.
You can use the DateTime object.
The object-oriented best way is:
$effectiveDate=$_REQUEST['effectiveDate'];
// here you must pass the original format to pass your original string to a DateTimeObject
$dateTimeObject = DateTime::createFromFormat('Y-m-d H:i:s', $effectiveDate);
// here you must pass the desired format
echo $dateTimeObject->format('Y-m-d H:i:s');