Why do I get two March instead of February then March when running the following code?
<?php
for($i=1; $i<= 12; $i++){
//MONTH NAME
$monthName = strftime('%B', mktime(0, 0, 0, $i));
if($i <= 9){
$monthNr = "0".$i;
}
else{
$monthNr = $i;
}
echo $monthNr . ':' . ucfirst($monthName) ."\n";
}
?>
Output:
01:January
02:March
03:March
04:April
05:May
06:June
07:July
08:August
09:September
10:October
11:November
12:December
It's because of this:
(from the mktime function reference)
Arguments may be left out in order from right to left; any arguments thus omitted will be set to the current value according to the local date and time.
If the current day is greater than the last day of the specified month, the extra days will extend the resulting timestamp into the next month. In this case today is the 30th, so February 30th becomes March 2nd.
If you add a day to mktime you'll get the result you're expecting.
$monthName = strftime('%B', mktime(0, 0, 0, $i, 1));
Related
I've been using the following function fine until the other day when the clocks went forward:
function months($month_format="F") {
$array = array();
for ($i = 1; $i <=12; $i++) {
$array[$i]['string'] = date($month_format, mktime(0,0,0,$i));
$array[$i]['int'] = date('m', mktime(0,0,0,$i));
}
return $array;
}
It outputs an array with:
string[]
int[]
Since the other day (like 2 days ago, when the clocks went forward in the UK), the function seems to be showing me 2 march months and 0 Februarys....
Very very strange...
I'm using rethinkdb with their eachPosTime function... not sure if this is causing it.
I tried using a different function, but still using mktime:
function months(){
$start_month = 1;
$end_month = 12;
$start_year = date("Y");
$array = array();
for($m=$start_month; $m<=12; ++$m){
echo $m.'<br>';
$array[$m]['string'] = date('F', mktime(0,0,0,$m));
$array[$m]['int'] = date('m', mktime(0,0,0,$m));
if($start_month == 12 && $m==12 && $end_month < 12)
{
$m = 0;
$start_year = $start_year+1;
}
//echo date('F Y', mktime(0, 0, 0, $m, 1, $start_year)).'<br>';
if($m == $end_month) break;
}
return $array;
}
Still, I am having no luck.
Check the image here, which shows the output of the months() function:
Output of the months() function
This is not to do with the clocks changing, but the time of the month, and the entirely unhelpful signature of the mktime function.
When you leave out parameters from a "mktime" call, they are filled in with today's date. In your case, you specified month without day or year, so when you ask for mktime(0, 0, 0, 2); it will fill in today's day and year, and look for the 29th February 2021 - a day that doesn't exist. Since the time library "overflows" dates, this becomes the 1st March.
The solution is to pass an explicit day to "mktime", as in mktime(0,0,0,$m,1) or to use a less confusing function.
Basically, I have a date set to today. From that date, I want to get the next and previous 20th day of the month. Basically, starting with 07/10/2020 (date of the post in d/m/Y format), I should end up with a date/timestamp to 20/09/2020 (previous 20th) and 20/10/2020 (next 20th).
I tried a few things and ended up with:
$ld_next_str = date("d/m/Y", strtotime("20 day this month"));
$ld_next_dt = DateTime::createFromFormat("d/m/Y", $ld_next_str);
$ld_prev_str = date("d/m/Y", strtotime("20 day last month"));
$ld_prev_dt = DateTime::createFromFormat("d/m/Y", $ld_prev_str);
But turns out this : "20 day this month" just adds 20 days to the current day so right now (on the seventh) it returns the 27th.
Knowing this, I figured I could probably just do something like subtracting the current day to that date (27 - 7 = 20) but I feel like there's probably a simpler way to do it, using strtotime without any extra steps.
Thanks in advance!
PS : I know you can get some days using "first" / "second" / "third" etc... but (I think) it doesn't go any higher than "twelfth", because I tried "twentieth" and that didn't work...
The formula for the previous 20th is:
mktime(0, 0, 0, $month - (1 - floor($day / 20)), 20, $year))
The formula for the next 20th is:
mktime(0, 0, 0, $month + floor($day / 20), 20, $year))
As a demo:
for ($month = 1; $month <= 12; $month++) {
for ($day = 1; $day <= 30; $day += 5) {
$prev = mktime(0, 0, 0, $month - (1 - floor($day / 20)), 20, 2020);
$next = mktime(0, 0, 0, $month + floor($day / 20), 20, 2020);
echo "$day/$month/2020: ", date('d/m/Y', $prev), ', ', date('d/m/Y', $next), PHP_EOL;
}
}
Outputs:
1/1/2020: 20/12/2019, 20/01/2020
6/1/2020: 20/12/2019, 20/01/2020
11/1/2020: 20/12/2019, 20/01/2020
16/1/2020: 20/12/2019, 20/01/2020
21/1/2020: 20/01/2020, 20/02/2020
26/1/2020: 20/01/2020, 20/02/2020
1/2/2020: 20/01/2020, 20/02/2020
6/2/2020: 20/01/2020, 20/02/2020
11/2/2020: 20/01/2020, 20/02/2020
16/2/2020: 20/01/2020, 20/02/2020
21/2/2020: 20/02/2020, 20/03/2020
...
Solution with an external class (a DateTime extension) that supports the cron syntax.
The string "0 0 20 * *" specifies the 20th of every month and every weekday at 00:00.
The nextCron() and previousCron() methods are used to determine the previous/next point in time based on a specific date.
$cronStr = "0 0 20 * *"; //every 20th 00:00
//source on https://github.com/jspit-de/dt
$next20 = dt::create('now')->nextCron($cronStr);
echo $next20; //2020-10-20 00:00:00
$prev20 = dt::create('now')->previousCron($cronStr);
echo $prev20; //2020-09-20 00:00:00
Outputs for the execution on October 8, 2020.
Here a better solution by using DateTime
$lastMonth = (new DateTime("last month"))->format("Y-m-20");
$thisMonth = (new DateTime("this month"))->format("Y-m-20");
$nextMonth = (new DateTime("next month"))->format("Y-m-20");
echo "$lastMonth - $thisMonth - $nextMonth";
I can display dates from start to end date from stored data in mysql, but I want to display current month dates from 1st to end date of this month in form of
1
2
3
4
.
.
.
.
.
31
Is this possible?
Refer to PHP cal_days_in_month
As explained here
This function will return the number of days in the month of year for the specified calendar.
int cal_days_in_month ( int $calendar , int $month , int $year )
And an example:
$number = cal_days_in_month(CAL_GREGORIAN, 8, 2003); // 31
echo "There were {$number} days in August 2003";
Use a loop to display a count of the number of days
For the PHP part, this might help you:
// Get the current date
$today = getdate();
// Get the number of days in current month
$days_in_month = cal_days_in_month(CAL_GREGORIAN, $today['mon'], $today['year']);
// Print the dates
for ($i = 1; $i <= $days_in_month; $i++) {
echo ' ' . $i;
}
Styling and output is another task, this is just to get you started.
yes. it is possible.
please, use below php code. it can work for php 4.1 and higher.
<?php
$number = cal_days_in_month(CAL_GREGORIAN, date('m'), date('Y'));
for($i=1;$i<=$number;$i++)
echo $i.'<br>';
?>
If you want all days in the month, try this loop where date("t") give you the numerical last day of the month, and we know the first day is always 1.
$last = date("t");
for($i=1; $i<= $last; $i++) echo "$i ";
I searched the millions of similar posts about this but cannot find how to make it count down from 31, 30, 29, 28 etc.
I can have the previous calendar blocks show the 31st but that's all. I need it to show previous month 31st, 30, 29, etc.
updated code from Renku:
//define the variable dayCol
$dayCol = 0;
// Print last months' days spots.
for ($i=0; $i<$leadInDays; $i++) {
$lastmonth = date('d', strtotime(-$i.' day', strtotime($startDate))); // Days in previous month
print "<td width=\"14%\" height=\"25%\" class=\"calendar_cell_disabled_middle\">$lastmonth</td>\n ";
$dayCol++;
}
example :
I am writing a new loop for this.
<?php
$StartDate= date("Y-F-d",strtotime("+0 Month"));// get first day of current month
$num= 10; // how many past days you need from previous month + 1 (to remove current day)
for ($i=1; $i<$num; $i++) {
echo $prev= date('Y-m-d', strtotime(-$i.' day', strtotime($StartDate)))."<br />"; //get last days of previous month
}
?>
I am re writing it with your loop,
<?php
$dayCol = 0;
$leadInDays = 5; // (just for February cuz theres 5 blanks before its the 1st of Feb)
$StartDate= date("Y-F-d",strtotime("+0 Month"));
// Print last months' days spots.
for ($i=1; $i<($leadInDays+1); $i++) {
$lastmonth = date('d', strtotime(-$i.' day', strtotime($StartDate))); // Days in previous month
print "<td width=\"14%\" height=\"25%\" class=\"calendar_cell_disabled_middle\">$lastmonth</td>\n ";
$dayCol++;
}
?>
Test it Here
I would use date('t') to get the number of days in said month and just loop backwards:
$month = '2013-02-05';
for($i = date('t', strtotime($month)); $i > 0; $i--) {
...
}
for ($y = 25; $y >= 7; $y--)
{
$showYear = false;
for ($m = 12; $m >= 1; $m--)
{
if (blogList($m, $y))
$showYear = true;
}
if ($showYear) {
echo '<h2>' . (2000 + $y) . '</h2>';
for ($m = 12; $m >= 1; $m--)
{
echo blogList($m, $y);
}
}
}
//blog archives
function blogList($month, $year)
{
$lastDate = array(31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
$beginDate = mkTime(0, 0, 0, $month, 1, $year);
$endDate = mkTime(0, 0, 0, $month, $lastDate[$month - 1], $year);
$query = .......;
}
i don't know why he set the $y=25.$showYear = false;
why the $lastDate = array(31,29,31,30,31,30,31,31,30,31,30,31);?
$y = 25 is because he's looping backwards from 2025 to 2007. $y ends up as the year argument for mkTime (see http://php.net/manual/en/function.mktime.php).
that array holds the last date of each calendar month, e.g. January has 31 days.
To show blog posts from 2007 to 2025.
The number of days in the month of each month.
However, don't try to learn from the above code!
Because blogList($m,$y) expects values for $y in the range of 7-25.
Those are the last dates of the months on a Gregorian calendar.
$lastdate holds the number of days in each of the 12 months of the year, and before running the query its trying to find the beginning and ending days of the month.
I'm not sure about the y=25 - that might depend on whats defined in the $query variable
1) Because it's the date from 2007 to 2025. The variable it's set to false because it needs to check something inside blogList, it's counting the days remaining to the end of the month, I think.
2) That's the last day of the month. The array has 12 elements.