For example I have 2 dates (year and month) like :
2013-03
2013-01 <-- Jan. current month.
2012-10
So my code is :
// Get current month and year
$m = date('m');
$y = date('Y');
// So I do something to get highest date so result is..
$highest = "2013-03";
// Current month and year
$current = $y."-".$m;
// So I do something to get lowest date so result is..
$lowest = "2012-10";
// My idea is get lower month from variables
function do_lower($date){
$date = explode("-",$date);
$y = $date[0];
$m = $date[1];
if($m != "01") {
$m = $m-1;
$m = sprintf('%02d',$m);
return $y."-".$m;
} else {
return ($y-1)."-12";
}
}
// This is my simple function to get result between high and low
function different($h,$l) {
global $data;
$h = do_lower($h);
if($h!=$l){
$data[] = $h;
different($h,$l);
}
}
Then .. to do all functions like.. (JSON)
$data[] = $highest;
different($highest,$current);
$data[] = $current;
different($current,$lowest);
$data[] = $lowest;
So my result is correct
["2013-03","2013-02","2013-01","2012-12","2012-11","2012-10"]
Anyone can review my code ?
Thanks so much
-
\$\begingroup\$ I'm confused. What's your end goal? Are you trying to list, in descending order, all dates between two given dates? \$\endgroup\$Corbin– Corbin2013年01月09日 09:24:20 +00:00Commented Jan 9, 2013 at 9:24
-
\$\begingroup\$ Yes you think right , Edited my code @Corbin \$\endgroup\$l2aelba– l2aelba2013年01月09日 09:27:26 +00:00Commented Jan 9, 2013 at 9:27
1 Answer 1
There's not really much to review here since it's such a short snippet, but a few things:
I tend to avoid manipulating dates as strings. With just a year-month format it's actually fine since there's no odd rules. It's generally a lot safer to use DateTime though (or even strtotime/date). The problem with dates and times are that they are not simple units. There are complex, ever-changing 'business rules' (of sorts) that surround dates and times and cause huge headaches.
As said though, you're fine with year-date
format since there's no gotcha's.
Just for consistency sake though, I would work with a standardized date format and use a date-time specific API.
For example:
$start = new DateTime(date('Y-m')); //First of this month
$end = new DateTime('2013-03'); //March 1st
$oneDay = new DateInterval('P1D');
$dates = array();
for (; $end >= $start; $end->sub($oneDay)) {
$dates[] = $end->format('Y-m');
}
$dates
is then an array in the format you want. This code is quite ugly, but unfortunately I've never been able to figure out a way to manipulate dates in PHP that isn't ugly.
Here's a strtotime/date based version:
$start = strtotime(date('Y-m'));
$end = strtotime('2013-03');
$dates = array();
while ($end >= $start) {
$dates[] = date('Y-m', $end);
$end = strtotime(date('Y-m-d', $end) . ' +1 day');
}
Rather than the strtotime call, you could just use 864000 seconds. I'd have to think for a few minutes to make sure that won't have any DST mistakes though. Once again, a situation where I like to keep date operations as abstracted away as possible. 864000 is a lie since not all days have 24 hours (at least not in places that observe DST).
If I were to go with a string approach, your do_lower function is basically what I'd use. It's named rather poorly though since it has no mention of what it's 'lowering' or what 'lowering' even means. Also, I would probably use a strict comparison against 01
.
The problem with a purely string based approach is that it's not very reusable. Your function has a very specific input format and a very specific output format. Anything else and it breaks.
If you pass around DateTime's instead, dates are no longer represented as a string. They're represented as a type that is much more appropriate for such a complicated system. They're represented as a type that is aware that they are a date.
-
\$\begingroup\$ Oh ! Nice answer , I will try your in my code :D thanks so much \$\endgroup\$l2aelba– l2aelba2013年01月09日 10:00:02 +00:00Commented Jan 9, 2013 at 10:00
-
1\$\begingroup\$ @l2aelba Glad to help :) \$\endgroup\$Corbin– Corbin2013年01月09日 10:02:11 +00:00Commented Jan 9, 2013 at 10:02