PHP format date in a dropdown not working - php

Im a bit stumped as i have some code to generate a simple dropdown of date for 21 days in advance.
It works fine as such however the output is not showing the right date instead its showing 1st Jan 1970
$timestamp = strtotime('today');
$output = [];
for ($day = 0; $day < 21; $day++) {
$output[] = date('d M y', strtotime(sprintf('+%d days', $day), $timestamp));
}
echo "<select name='days'>";
foreach ($output as $day)
{
echo "<option value='".$day."'>".date('l jS \of F Y',$day)."</option>";
}
echo "</select>";
if i echo just $day as the outpout value it displays in the DD/MM/YYYY format but i want it to display Day Name Date of Month Year
so whats not correct with using
date('l jS \of F Y',$day)
Im sure its something dumb but ive checked over all the various posts around on date but i cant for the life of me figure this out.

The function date() takes as its second argument a time in seconds.

If you look at the PHP:date documentation, you'll find that the second argument expects an integer, not a string.
Change your code to the following:
<?php
$output = [];
for ($day = 0; $day < 21; $day++) {
$output[] = strtotime(sprintf('+%d days', $day));
}
echo "<select name='days'>";
foreach ($output as $day)
{
echo "<option value='".$day."'>".date('l jS \of F Y', $day)."</option>";
}
echo "</select>";
Rather than filling your output array with strings, you'll see here that we instead fill it with 21 timestamps.
Once you begin looping through your output array, passing in the timestamp to the second argument of the date function will yield the output you're expecting.
I'm keeping the value of each option set to that timestamp, as it makes everything easier to work with if you need to process any POST data. But you're free to adjust the formatting there as needed.
Here's a working example that you can play around with.
Edit:
Just for funsies, here's how you can do it in a more object-oriented style. I feel it's a little more succinct this way, but it's up to you if you want to take this approach or not.
<?php
$today = new DateTime();
echo "<select name='days'>";
for ($day = 0; $day < 21; $day++)
{
echo "<option value='".$today->getTimestamp()."'>".$today->format('l jS \of F Y')."</option>";
$today->add(new DateInterval("P1D"));
}
echo "</select>";

Related

Compare month in two custom date fields using datetime

our site does festival reviews, and for this we want to be able to select a start date (datum) and an end date (eind_datum) via date time picker custom fields. Ultimately we want a function that determines whether the start and end date have the some month, so we end up with something like this
'1-4 Juli 2020' (instead of '1 Juli - 4 Juli 2020).
When the month is different we want it to be displayed as follows
'30 Juni - 4 Juli 2020'.
I have tried several things but none seem to work, the month needs to be in Dutch, I tried setting the locale but that didn't help, and the following code below throws an error at this line
'$first = $startdateTime->format('F');'
Anybody out here who might help ?
<?php
$start_date = get_field('datum');
$end_date = get_field('eind_datum');
$startdatetime = DateTime::createFromFormat('Y-m-d H:i:s', $start_date);
$enddatetime = DateTime::createFromFormat('Y-m-d H:i:s', $end_date);
$first = $startdateTime->format('F');
$second = $enddateTime->format('F');
if (get_field('eind_datum') and get_field('datum') and ($first == $second )) {
echo $start_date->format ('j'); echo "-"; echo $end_date->format ('j F Y') ;
}
elseif (get_field('eind_datum') and get_field('datum') and ($first != $second )) {
echo $start_date->format('j F'); echo "-"; echo $end_date->format ('j F Y') ;
}
else {
echo the_field('datum') ;
}
?>
The following should work:
$start_date = get_field('datum');
$end_date = get_field('eind_datum');
$startdatetime = new DateTimeImmutable($start_date);
$enddatetime = new DateTimeImmutable($end_date);
$first = $startdatetime->format('F');
$second = $enddatetime->format('F');
if ($start_date and $end_date and ($first == $second )) {
echo $startdatetime->format ('j'); echo "-"; echo $enddatetime->format ('j F Y') ;
}
elseif ($end_date and $start_date and ($first != $second )) {
echo $startdatetime->format('j F'); echo "-"; echo $enddatetime->format ('j F Y') ;
}
else {
echo $start_date;
}
The problem in you code is that the variables are sometime called incorrectly. For example: $start_date is not an object, and you cannot call the method format on it... or $startdateTime is not defined it is rather $startdatetime
Instead of creating 2 formats under certain conditions, you can also create the format '1 July - 4 July 2020' and then remove the month with preg_replace () if the months are the same.
$dateStr = '1 Juli - 4 Juli 2020';
$dateStr = preg_replace('~^(\d+) (\w+) - (\d+) (\2)~',"$1-$3 $2",$dateStr);
If the months are unequal, nothing is removed.

How to loop 2 dates to output like this?

Here's my code that display date with for loop.
Topic: Im creating a script to generate payment due(from to start).
$y = 1;
$period = 3;
$start = date('m/15/Y');
echo "<table>";
echo '<thead><th>From</th>';
echo '<th>To</th></thead>';
for ($y; $y <= $period; $y++) {
$month_mid = date("m/15/Y", strtotime($start));
$month_last = date("m/t/Y", strtotime($start));
echo '<td>'.$month_mid = date("m/t/Y", strtotime($start)).'</td>';
echo '<td>'.$month_last = date("m/15/Y", strtotime($start)).'</td></tr>';
$start = date("m/d/Y",strtotime($start." +1month"));
}
echo '</table>';
output I get:
09/15/2017 09/30/2017
10/15/2017 10/31/2017
11/15/2017 11/31/2017
I want to appear like this:
09/15/2017 09/30/2017
09/30/2017 10/15/2017
10/15/2017 10/31/2017
Im new in date php hope you can help me with this thanks.
Here you go:
$y = 1;
$period = 5;
$start = date('m/15/Y');
echo "<table>";
echo '<thead><th>From</th>';
echo '<th>To</th></thead>';
for ($y; $y <= $period; $y++) {
$month_mid = date("m/15/Y", strtotime($start));
$month_last = date("m/t/Y", strtotime($start));
echo '<tr><td>'.$month_mid = date("m/t/Y", strtotime($start)).'</td>';
echo '<td>'.$month_last = date("m/15/Y", strtotime($start)).'</td></tr>';
$start = date("m/d/Y",strtotime($start." +1month"));
}
echo "</table>";
You missed the opening and clousure of table and <tr>.
You don't want to be skipping ahead by a month in your loop. Well, not the way you are doing it here.
You should use DatePeriod::getEndDate and DatePeriod::getStartDate, along with DateTime::add to skip by semi-monthly amounts. The idea is that you only get to the next month by letting the datetime API add 15 days to a given start date, and use that to figure out the mid-month and end-month dates.
Keep everything in these date objects until you need to format and print them, and save the second one in the pair as input for the next round of the loop at the end where you just have to calculate the new second value.
I feel like you could write a function that gets the "next" date from any other first or last date of the month to simplify the loop.
(Since this is semi-monthly and not bi-weekly, you can actually just walk the months in your period, hard-coding the 15th for one value and using your end-of-month function for the second. It depends on your requirements and how complicated the API gets.)
Or
For each month in your period, calculated the mid-month (i.e., exactly 15 days from the start of the month) and end-month dates. Save them in a Collection of couplets of some sort.
Write a display routine that takes this Collection and outputs the dates, but saves the previous formatted string made from the second item in the couplet as the first item to be printed (after the first line.)
I actually prefer this one because it separates the presentation from the data abstraction, allowing you freedom to display and format the date how you see fit.
But, at the end of the day (pun not intended, but what a great pun), stop using date strings as input to figure out other dates when you have access to normalized epoch representations. This will only lead to madness.
$y = 1;
$period = 3;
$start = date('m/d/Y');
$end = date('m/t/Y');
echo "<table>";
echo '<thead><th>From</th>';
echo '<th>To</th></thead>';
for ($y; $y <= $period; $y++) {
echo '<tr><td>'.$start.'</td>';
echo '<td>'.$end.'</td></tr>';
$getLast = date('d',strtotime($end));
if($getLast >= 28) {
$start = date("m/t/Y", strtotime($start));
$end = date("m/d/Y", strtotime("+15 day", strtotime($end)));
}else {
$start = date("m/d/Y", strtotime("+15 day", strtotime($start)));
$end = date("m/t/Y",strtotime($end));
}
}
echo "</table>";
Result:
From To
09/15/2017 09/30/2017
09/30/2017 10/15/2017
10/15/2017 10/31/2017

how to get 4-days ago to now - php

If current date is 2016-03-06, I would like to get these dates :
2016-03-06
2016-03-05
2016-03-04
2016-03-03
I'm trying to get this purpose but my result not what I want :
$_4date = date("y-m-d",strtotime("day"));
$_3date = date("y-m-d",strtotime("-1 day"));
$_2date = date("y-m-d",strtotime("-2 day"));
$_1date = date("y-m-d",strtotime("-3 day"));
echo $_4date;
echo '<br />';
echo $_3date;
echo '<br />';
echo $_2date;
echo '<br />';
echo $_1date;
the result is :
70-01-01
16-03-05
16-03-04
16-03-03
To get today's date with strtotime, you do strtotime("today");. However, as Bjorn has commented, you can simply just call date() directly.
Furthermore, the reason you are not getting the year in four digits is because you are using a lowercase y instead of an uppercase Y.
Try date("Y-m-d", strtotime("-1 day"));.
The following piece of code illustrates the required changes:
$today = date("Y-m-d");
$yesterday = date("Y-m-d", strtotime("-1 day"));
echo "$today <br />";
echo "$yesterday <br />";
// Output
2016-03-06
2016-03-05
For more informtation, please consult the PHP documentation on the date function. It actually shows you that what to expect from y and Y and it also shows you that the default value that is passed as the second argument is time(), meaning the default is the current time.
PHP's strtotime documentation can be consulted for more information on the strtotime() function and its possible parameters.
Always check the (PHP) documentation first before asking a question.
You need to use like that:
$_4date = date("Y-m-d");
$_3date = date("Y-m-d",strtotime("-1 day"));
$_2date = date("Y-m-d",strtotime("-2 day"));
$_1date = date("Y-m-d",strtotime("-3 day"));
Explanation:
For current date no need to use use strtotime().
For full year you need to use this format Y-m-d.
y-m-d will return you the date 16-03-06 but Y-m-d will return you 2016-03-06.
Use a for loop with strtotime( "... days ago" ):
for( $i = 0; $i < 4; $i++ )
{
echo date( 'Y-m-d', strtotime( "$i days ago" ) ) . PHP_EOL;
}
The first loop (0 days ago) will output today date, other loops will output past days.
3v4l.org demo
You need to use capital 'Y' for full year (2016) instead of small 'y' which will display year in shorthand (16).
And for current date just use date("Y-m-d").
<?php
$_4date = date("Y-m-d");
$_3date = date("Y-m-d",strtotime("-1 day"));
$_2date = date("Y-m-d",strtotime("-2 day"));
$_1date = date("Y-m-d",strtotime("-3 day"));
echo $_4date;
echo '<br />';
echo $_3date;
echo '<br />';
echo $_2date;
echo '<br />';
echo $_1date;
?>
Working Example
<?php
$date = [date("Y-m-d")];
for($i = 1; $i < 4; $i++) {
$date[] = date("Y-m-d",strtotime("-$i day"));
}
//For cli output you'll need:
echo implode("\n", $date) . "\n";
//For web output you'll need:
echo implode("<br />", $date) . "<br />";

loop array values

Here I access 'date' key values from rows of DB table. And I can echo these values, no problem.
$res = $mysqli->query("SELECT * FROM alfred ORDER BY id ASC");
$row = $res->fetch_all(MYSQLI_ASSOC);
foreach ($row as $key => $value){
$availDate = $value['date'];
echo $availDate.'<br />';
}
This loop above shows all 'date' values from DB, in this case there are 3 dates- "2012-09-25" "2012-09-27" and "2012-09-29".
But then I need to compare each of these 'date' values against values of $date->format('Y-m-d') from the code below and display each date with corresponding "busy" or "available" status into separate <td> of the table. My following version compares only the "last" value of 'date' key - "2012-09-29", but I need to compare each 'date' value from the array above, it means also "2012-09-25" and "2012-09-27". I have tried many versions but still unsuccessful. Any ideas?
$date = new DateTime();
$endDate = new DateTime('+10 day');
for($date->format('Y-m-d'); $date->format('Y-m-d') < $endDate->format('Y-m-d'); $date->modify('+1 day')){
if ($date->format('Y-m-d') == $availDate){
echo '<td>'.$date->format('Y-m-d/D').' busy</td>';
} else {
echo '<td>'.$date->format('Y-m-d/D').' available</td>';
}
}
Here is the result I am getting now:
2012-09-21/Fri available 2012-09-22/Sat available 2012-09-23/Sun available 2012-09-24/Mon available 2012-09-25/Tue available 2012-09-26/Wed available 2012-09-27/Thu available 2012-09-28/Fri available 2012-09-29/Sat busy 2012-09-30/Sun available
But in fact I need to show "busy" status also into <td> of "2012-09-25" and <td> of "2012-09-27" as these also are 'date' values that are existing in $row array. Unfortunately I can not post any images here to show, but I hope my result above gives you the idea.
SOLVED with the help of in_array below:
$aAvailDate = array();
foreach ($row as $key => $value){
$aAvailDate[] = $value['date'];
}
$date = new DateTime();
$endDate = new DateTime('+10 day');
for($date->format('Y-m-d'); $date->format('Y-m-d') < $endDate->format('Y-m-d'); $date->modify('+1 day')){
if (in_array($date->format('Y-m-d'), $aAvailDate)){
echo '<td>'.$date->format('Y-m-d/D').' busy</td>';
} else {
echo '<td>'.$date->format('Y-m-d/D').' available</td>';
}
}
I haven't tested your code, but I think you are running ->format('Y-m-d') unnecessarily here, and this is messing up your logic.
Every time you run that, PHP is turning your object into a string, which you are then comparing against other strings. This won't do anything useful.
Instead, you should be using the features of the DateTime class to compare the objects themselves. The only time you should need to use the format() method is when outputting to the browser, into an SQL query, etc
Although your Question is Unclear but AFAIK
you want to display "Busy" if available date occurs between given date upto 3 Weeks
otherwise display "free"
I would like to suggest you to do this with MySQL (Not tested)
SELECT *,
IF( `DateCol` BETWEEN NOW() AND DATE_ADD(NOW(), INTERVAL 3 WEEK), 'Busy','Free')
AS status
FROM TableName
Try a while loop instead of a foreach. Also, compare the DateTime objects directly, not the formatted strings.
$date = new DateTime();
$endDate = new DateTime('+3 week');
while( $date < $endDate) {
if ($date->format('Y-m-d') == $availDate){
echo '<td class="busy">busy</td>';
} else {
echo '<td>free</td>';
}
$date->modify("+1 day");
}
Something like this? (If I understand what you're trying to do correctly)
<?php
$avail_dates = array();
$res = $mysqli->query("SELECT DATE_FORMAT(date, '%Y-%m-%d') AS availDate FROM alfred ORDER BY id ASC");
$row = $res->fetch_all(MYSQLI_ASSOC);
foreach ($row as $key => $value){
$avail_dates[] = $value['availDate'];
}
$startDate = date('Y-m-d');
$endDate = date('Y-m-d', strtotime(date("Y-m-d", strtotime($startDate)) . " +3 week"));
?>
<table>
<?php
foreach ($avail_dates as $availDate){
echo "<tr><td>$availDate</td>";
if (($startDate <= $availDate) && ($endDate >= $availDate)){
echo "<td class='busy'>busy</td>";
}else{
echo "<td>free</td>";
}
echo "</tr>";
}
?>
Instead of printing values, I would add them to the array, and then run a loop on that array, comparing the values to the given start and end dates. I also wouldn't fetch all from the table if you nly need a date.
May be like this?
$date = new DateTime();
$endDate = new DateTime('+3 week');
for($date->format('Y-m-d'); $date->format('Y-m-d') < $endDate->format('Y-m-d'); $date->modify('+1 day')){
$tempDate = $date->format('Y-m-d');
if ($tempDate === $availDate){
echo '<td class="busy">busy</td>';
} else {
echo '<td>free</td>';
}
}

Getting the next date of a day in MySQL database (PHP)

I have a series of weekly events in a database along with the day they happen on (in full form, so: 'Monday', 'Tuesday' etc). I've successfully printed the events in a while loop ordered by today, tomorrow, etc, but I'd like to put the date in brackets next to each one.
I thought it might be a case of (mock code):
$today = date("l");
$todays_date = date("j M");
if (day == $today) {
$date = $todays_date;
}
else if (day == $today + 1) {
$date = $todays_date + 1;
}
else if (day == $today + 2) {
$date = $todays_date + 2;
}
etc...
But I'm not so sure. It'd be ideal if I could just have the date in the database, but this seems to go against the grain of what MySQL is about.
Also, I'd like to ideally format the date as: 11 Jun.
EDIT
Presumably it's also got to fit into my while loop somehow:
if($result && mysql_num_rows($result) > 0) {
while ($row = mysql_fetch_array($result)) {
$items[] = array($row[0]);
echo "<option>" . $row[0] . "</option>";
}
}
You can use strtotime?
echo "Today: ".date("j M");
echo "Tomorrow: ".date("j M", strotime("+1 day"));
You can use strtotime:
echo strtotime("+1 day");

Categories