I need to create next and previous link urls
here's a sample
previous
<? echo $_GET['month'].', '.$_GET['year']; // shows 11, 2009
next
where the 2nd segment is the year and the first segment is the month
I've got the month and the year in the GET array, but any ideas how best to do this?
I was thinking prevmonth = month-1, but then if the previous month was a new year, that would get all messed up.
You can use mktime with out-of-range values to do things like this. See the example #2 on the manual page.
e.g. echo date("M-d-Y", mktime(0, 0, 0, 13, 1, 1997)); will give 1998-01-01.
strtotime() makes it pretty easy.
$year = 2009;
$month = 5;
$nextMonth = strtotime('+1 Month', strtotime($year.'-'.$month.'-01'));
echo date('Y/m', $nextMonth);
Fairly easy to catch that sort of logic...? Just inc/dec the year if your month goes out of bounds...
#sanity check inputs
$month=min(max(intval($_GET['month']), 1),12);
$year=intval($_GET['year']);
$prev=array($month-1, $year);
if ($prev[0]==0)
{
$prev[0]=12;
$prev[1]--;
}
$next=array($month+1, $year);
if ($next[0]==13)
{
$next[0]=1;
$next[1]++;
}
I think the easiest way would just be to check for the "previous month < 1" condition and decrement the year. There might be a more clever way to do this, but this is easy enough to understand:
$prevyear = intval($_GET['year']);
$prevmonth = intval($_GET['month']) - 1;
// Check for year rollover.
if ( $prevmonth < 1 ) {
$prevmonth = 12;
$prevyear = $prevyear - 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.
I have the following piece of code on a site I'm working on. It was written by a previous developer, so I am unsure of exactly how to deal with it:
$datetime = new DateTime("$dt_start_ymd +$gap month");
$dt_next = new DateTime("Thursday " . $datetime->format('Y-m-01'));
$dt_next_0 = $dt_next->setTime(02, 00)->getTimestamp();
$dt_next = $dt_next->getTimestamp();
The variable $gap is an incrementing count (1, 2, 3, etc). The code above should output a sequence of dates listing the first thursday for each month for a number of months as indicated by $gap
i.e. 05/07/2017, 03/08/2017, 07/09/2017 (those being the first Thursday of those respective months).
The code works fine on most dates, but for a reason I cannot fathom if it is passed a date that is the 31st of a month (i.e. 2017-05-31) the system breaks and outputs incorrect answers.
I think this code is unnecessarily complicated. In addition, you're in a situation where if the given date is the 31st and you attempt to add 1 month, you're ending up in a situation where it's attempting to find the 31st of the next month, which does not exist except in December->January.
You might want to consider something like
$currentDate = new \DateTime();
$iterations = 10;
for ($i = 0; $i < $iterations; $i++) {
$first_thursday = new \DateTime(
sprintf('first Thursday of %s', $currentDate->format('F Y'))
);
$nextDate = new \DateTime($currentDate->format('Y-m-d'));
$nextDate->add(new \DateInterval('P1M'));
if ($nextDate->format('m') > $currentDate->format('m') + 1) {
$nextDate->sub(new \DateInterval('P1D'));
}
$currentDate = $nextDate;
echo $first_thursday->format('Y-m-d');
}
This will give you the first Thursday in every month for the next 10 months, and I think is much easier to read than the example you gave.
EDIT: I've updated the code so that it doesn't skip out months. See my comment below.
I'm using this code to get number of days in last month, but if the current month is January (01) it's going to use 00 month instead of 12.
$prev_month_days = cal_days_in_month(CAL_GREGORIAN, date('m')-1, date('Y'));
Searched Google for 20 minutes and could not find any reasonable and shorthand solution.
Please help. Thanks.
<?php
echo date("t", mktime(0,0,0, date("n") - 1));
?>
The example provided by Dan is not correct.
You have to check the result of date("n") and correct for January return
And if this is part of a time function, which seems logical since you are looking for the previous number of days in a month. You will also have to compensate for the year shifting back. Otherwise you would shoot to December of the current year.
What works better is..
$NowYear = date("Y");
$NowMonth = date("n");
if ($NowMonth == 1) {
$ThenMonth = 12;
$ThenYear = $NowYear - 1;
}
else {
$ThenMonth = $NowMonth - 1;
$ThenYear = $NowYear;
}
$ThenNumberOfDays = date("t", mktime(0, 0, 0, $ThenMonth, 1, $ThenYear));
$ThenNumberOfDays would have the correct number of days...
I have a calendar that I want to allow events to be repeated on a week day of the month. Some examples would be:
Repeat every 4th Tuesday of the month
Repeat every 2nd Friday of the month
And so on...
What I need is the ability to find out how many week days (for example Tuesday's) have passed this month so far.
I found some code that returns how many Monday's have passed.
$now=time() + 86400;
if (($dow = date('w', $now)) == 0) $dow = 7;
$begin = $now - (86400 * ($dow-1));
echo "Mondays: ".ceil(date('d', $begin) / 7)."<br/>";
This works well but how do I make it so that I can determine any week day? I cannot seem to get my head around the code to make this work.
strtotime is really useful for this kind of thing. Here are lists of the supported syntax. Using your example of repeat every 2nd Friday of the month I wrote the following simple snippet for you:
<?php
$noOfMonthsFromNow=12;
$dayCondition="Second Friday of";
$months = array();
$years = array();
$currentMonth = (int)date('m');
for($i = $currentMonth; $i < $currentMonth+$noOfMonthsFromNow; $i++) {
$months[] = date('F', mktime(0, 0, 0, $i, 1));
$years[] = date('Y', mktime(0, 0, 0, $i, 1));
}
for ($i=0;$i<count($months);$i++){
$d = date_create($dayCondition.' '.$months[$i].' '.$years[$i]);
if($d instanceof DateTime) echo $d->format('l F d Y H:i:s').'<br>';
}
?>
This can be tested at: http://www.phpfiddle.org/lite/
$beginningOfMonth = strtotime(date('Y-m-01')); // this will give you the timestamp of the beginning of the month
$numTuesdaysPassed = 0;
for ($i = 0; $i <= date('d'); $i ++) { // 'd' == current day of month might need to change to = from <= depending on your needs
if (date('w', $beginningOfMonth + 3600 * $i) == 2) $numTuesdaysPassed ++; // 3600 being seconds in a day, 2 being tuesday from the 'w' (sunday == 0)
}
Not sure if this will work, and there's probably a better way to do it; don't have the means to test it right now but hopefully this puts you on the right track! (I get tripped up on date math a bit too, especially with timezones)
I am trying to get stripe to set a end_trial date on the next occurrence of whatever day of the month the user chooses. i.e. If today is the 16th and the user chooses the 15th I need the unix timestamp for the 15th of the next month. However if today was the 14th I need the timestamp for tomorrow.
I tried the solution found on this SO question Find the date for next 15th using php .
When i ran the code suggested in that question and substituted 15 for 31
$nextnth = mktime(0, 0, 0, date('n') + (date('j') >= 31), 31);
echo date('Y-m-d', $nextnth);
The result is 2013-03-03
I also tried this one Get the date of the next occurrence of the 18th .
The second one would actually give me 2013-03-31 when i ran it one 2013-1-31.
Both had unexpected results. Is february the problem? Any guidance will be much appreciated.
Here is a way to do it.
function nextDate($userDay){
$today = date('d'); // today
$target = date('Y-m-'.$userDay); // target day
if($today <= $userDay){
$return = strtotime($target);
}
else{
$thisMonth = date('m') + 1;
$thisYear = date('Y');
if($userDay >= 28 && $thisMonth == 2){
$userDay = 28;
}
while(!checkdate($thisMonth,$userDay,$thisYear)){
$thisMonth++;
if($thisMonth == 13){
$thisMonth = 1;
$thisYear++;
}
}
$return = strtotime($thisYear.'-'.$thisMonth.'-'.$userDay);
}
return $return;
}
// usage
echo date('Y-m-d',nextDate(29));
We get the user's choice and compare it today.
If today is less than or equal to user choice, we return the timestamp for this month.
If today is greater than user choice, we loop through dates, adding a month (or a year if it's $thisMonth hits 13). Once this date does exist again, we have our answer.
We check the dates using php's checkdate function, strtotime and date.
I really don't understand the question completely. You can easily determine the date for next 30 days for example
$next_ts = time() + 30 * 86400; // add 30 days to current timestamp
$next = date('Y-m-d', $next_ts); // format string as Y-m-d
echo $next;
If that is not what you need, please explain the problem.