Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialMichael Hodges
10,826 PointsPracticing math and if/else conditions, have a bug in my code.
I was just playing around with PHP, practicing with conditionals, and doing math stuff. We just had a baby and I thought I'd use that as an excerise to practice something, so I wanted to create a program that would calculate her age from the second she was born. It would say something like this: 1 year 2 months 3 weeks 4 days 5 hours 6 minutes 7 seconds
Though being just born earlier this month, only parts of that would be displayed, so I intentionally modified the starting time variable in the beginning to test things out, adding time (technically subtracting epoch time) increments to test the math and if/else statements . It seems to work out ok until it gets to the hours/minutes/seconds lines. I'm not entirely sure where I'm going wrong on this and I was hoping someone could see it.
Here's the code in full:
date_default_timezone_set('America/New_York');
$minute = 60;
$hour = 3600;
$day = 86400;
$week = 604800;
$month = 2629743; // 30.44 days
$year = 31556926; // 365.24 days
$riley = 1421197860; // Riley's birth: Jan 13th, 2015 at 8:11pm
//$riley = 1421197860 - $year - $year; // test variable to change date in year/month/week/etc increments
$now = time();
$difference = $now - $riley;
echo date('r', $riley) . ", epoch: " . $riley . "\n"; // display birth date/time
echo date('r') . ", epoch: " . $now . "\n"; // current date/time
echo "difference: " . $difference . "\n"; // total difference in seconds
echo "\n";
// calculate years and grab remainder seconds
if ($difference >= $year) {
$rileyYears = floor($difference / $year);
if ($rileyYears != 1) {
echo $rileyYears . " years\n";
}
else {
echo "1 year \n";
}
$remainder = $difference - ($rileyYears * $year);
} else { $remainder = $difference; }
// calculate months and grab remainder seconds
if ($remainder >= $month) {
$rileyMonths = floor($remainder / $month);
if ($rileyMonths != 1) {
echo $rileyMonths . " months\n";
}
else {
echo "1 month \n";
}
$remainder = $difference - ($rileyMonth * $month);
} else { $remainder = $difference; }
// calculate weeks and grab remainder seconds
if ($remainder >= $week) {
$rileyWeeks = floor($remainder / $week);
if ($rileyWeeks != 1) {
echo $rileyWeeks . " weeks\n";
}
else {
echo "1 week \n";
}
$remainder = $difference - ($rileyWeeks * $week);
} else { $remainder = $difference; }
// calculate days and grab remainder seconds
if ($remainder >= $day) {
$rileyDays = floor($remainder / $day);
if ($rileyDays != 1) {
echo $rileyDays . " days\n";
}
else {
echo "1 day \n";
}
$remainder = $difference - ($rileyDays * $day);
} else { $remainder = $difference; }
// calculate hours and grab remainder seconds
if ($remainder >= $hour) {
$rileyHours = floor($remainder / $hour);
if ($rileyHours != 1) {
echo $rileyHours . " hours\n";
}
else {
echo "1 hour \n";
}
$remainder = $difference - ($rileyHours * $hour);
} else { $remainder = $difference; }
// calculate minutes and grab remainder seconds
if ($remainder >= $minute) {
$rileyMinutes = floor($remainder / $minute);
if ($rileyMinutes != 1) {
echo $rileyMinutes . " minutes\n";
}
else {
echo "1 minute \n";
}
$remainder = $difference - ($rileyMinutes * $minute);
} else { $remainder = $difference; }
// calculate remaining seconds
if ($remainder >= 1) {
if ($remainder != 1) {
echo $remainder . " seconds\n";
}
else {
echo "1 second \n";
}
}
3 Answers
thomascawthorn
22,986 PointsWhat I see in your code is you running the same check over and over.. If only there was something you could use instead of repeating all that functionality.. Oh wait! Loops! Yay loops!
This is a slight tangent, but it should clean your code and make it 20 lines instead of 200.
You have this as your current structure:
<?php
// calculate minutes and grab remainder seconds
if ($remainder >= $minute) {
$rileyMinutes = floor($remainder / $minute);
if ($rileyMinutes != 1) {
echo $rileyMinutes . " minutes\n";
}
else {
echo "1 minute \n";
}
$remainder = $difference - ($rileyMinutes * $minute);
} else { $remainder = $difference; }
I would create a variable that contained an array of the time units you wanted to calculate and associate those like you have done above. I've used a foreach loop below, but a 'for' loop might be better.
<?php
// This is your lookup array
$lookupTimeUnits = array(
'year' => 31556926,
'month' => 2629743,
'week' => 604800,
'day' => 86400,
'hour' => 3600,
'minute' => 60,
'second' => 1,
);
// prepare an output string
$output = '';
// here's your loop
foreach ($lookupTimeUnits as $timeUnit => $timeUnitSeconds)
{
if ($remainder >= $timeUnitSeconds) {
$timeUnitForSeconds .= floor($remainder / $timeUnitSeconds);
if ($timeUnitForSeconds != 1) {
$output "{$timeUnitForSeconds} {$timeUnit}s \n";
}else {
$output .= "1 {$timeUnit} \n";
}
$remainder = $difference - ($timeUnitForSeconds * $timeUnitSeconds);
} else {
$remainder = $difference;
}
}
echo $output;
I haven't tested this, but hopefully you can see what I'm getting at and have a go at making it work.
It is a really good rule of thumb to try and exclude else blocks i.e. how can you write your code where an else block would be needed? Another good suggestion is to go only one level deep. I.e. try to nest if/else conditionals and loops inside one another.
Anyway, if you can make your code work in the loop above, it should work perfectly for every time unit you wanted to pass in.
Also if you have a timestamp, could you not just do:
<?php
// This is your lookup array
$lookupTimeUnits = array(
'year' => 'Y',
'month' => 'm'
'day' => 'd',
);
//etc...
// prepare an output string
$output = '';
// here's your loop
foreach ($lookupTimeUnits as $timeUnit => $dateFormat)
{
$timeUnitForSeconds = date($dateFormat, $timestamp);
if ($timeUnitForSeconds != 1) {
$output "{$timeUnitForSeconds} {$timeUnit}s \n";
}else {
$output .= "1 {$timeUnit} \n";
}
}
echo $output;
Michael Hodges
10,826 PointsHi Jen, yeah I know there are date functions to make some things easier, I was just intentionally doing things from scratch to play with math and logic.
Thanks Tom, I'll play with that looping concept and see what I can make work. That does add a dictionary-like array to the mix for more fun too I suppose.
Jen Ollivierre
929 Pointsarrays, for loop, foreach loops are fun bro, enjoy them. I use to try making my own maths to calculate date, had too many horrors so I went native php hehe
Jen Ollivierre
929 PointsJen Ollivierre
929 PointsPHP has an easy way to do this, which would save time, but I like your thought, get the old brain working to test your logical and mathematical thinking. Signs of a true PHP lover. Anyhow, here is the easier way with using PHP native function date_create.
$current_date = date("d-m-Y"); $date1 = date_create($current_date); // Current Date // $date2 = date_create("15-10-2014"); // Baby birthdate // $date3 = date_diff($date2,$date1);
$days = $date3->d; $months = $date3->m; $years = $date3->y;
so echo $years." ".$months." ".$days would give the amount of year, month and days born. If you echo $days by itself, it would give how many days gone in a month. So if birthday is the 20th, and the date is currently the 10th of the next month, it would say 20 days. When the 20th comes back around, days echo would be zero.
This saves you a lot of headache, far simpler coding.
You can then add your conditional if statements like
if ($year < 1) { if ($month < 1) { echo "baby is now ".$days." old"; } } else if ($year > 1) { if ($month < 1) { echo "baby is now ".$year." and ".$days." old"; } } .....
etc etc.