<?php
/*
* Fuzzy Time function
* Written at some point late in April.
* Takes in two variables, one optional - $time, the time needed to work with, in epoch, and $divide, a boolean variable which basically decides if the script should first subtract the current time in epoch, with the number provided.
* Licensed under the Creative Commons Attribution-Noncommercial Share-Alike 2.5 license for UK: Scotland
* http://creativecommons.org/licenses/by-nc-sa/2.5/scotland/
* As much as you really don't have to, I'd appreciate a head's-up if you ever decide to use my code anywhere. It'd make me feel all great and such :D

* This script essentially takes in an epoch number, and works about to figure out how long ago it was, then output something fuzzy and human-readable (Such as "around five minutes ago")
* This was actually coded mostly for my website. I wanted an easy, timezone-insensitive function for fuzzy time, because I felt it was nicer than what's provided by last.fm's data feeds. I later realised epoch was still timezone-sensitive.
*/

function fuzzy($time$subtract 0) {
    
//The function can really be called with something like "fuzzy('540');" and it would still work, there's no need to use something like "fuzzy('540',1);"
    //Check if $subtract is 1. If it is, subtract by current epoch time.
    //I thoroughly recommend doing epoch subtraction before using the function, because epoch is still timezone-sensitive, even if solving it is as easy as just subtracting the timezone offset (For me I would subtract 3600 seconds. Unless I'm using it on my web server, which is in sweden. In this case I subtract 7200 seconds. This is two hours.)
    //This is done before checking if the time is in the future so we don't need to revalidate after subtraction.
    
if($subtract == 1) {
        
$time time() - $time;
    }
    
//Validate input for subtraction variable.
    
else if($subtract != 0) {
        
//I was tired when I coded this, it's probably silly.
        
return "Incorrect usage (function should be called with either fuzzy(INT-EPOCH) or fuzzy(INT-EPOCH, BOOL)";
    }
    
//Check if the time is in the past
    
if($time 0) {
        
//It's in the future. We don't bother making futuretime fuzzy, however we don't simply crash the script there.
        
return "at an unknown time";
    }
    
//Future-time fuzzying could easily be implemented, I just see no need to.
    //Check if it's in the last 1 minute.
    
if($time 60) {
        
$period "second";
        
//Grammar is important, turn the string into "Seconds" if it's more than one second ago.
        
if($time != 1) {
            
$period .= 's';
        }
        
//In the script's original form, this would simply output "Right now".
        
return "$time $period ago";
    }
    
//Divide by 60 to put the epoch into minutes, then check if it's in the last hour.
    
$time /= 60;
    
$time floor($time);
    if(
$time 60) {
        
$period "minute";
        if(
$time 1) {
            
$period .= 's';
        }
        
//In the script's original form, this would output "Moments ago" if the time was within the last 3 minutes.
        //Format time into minutes
        
$mins floor($time);
        return 
"$time $period ago";
    }
    
//Divide by 60 to put epoch into hours, then check if it's within the last day.
    
$hours floor($time 60);
    
$mins $time - ($hours 60);
    
$time /= 60;
    
//We now have hours and minutes.
    
if($time 24) {
        
$period "hour";
        if(
$hours 1) {
            
$period .= 's';
        }
        
//This is here to prevent output like "2 and a half hourss ago", which was a problem I didn't notice when I originally coded this.
        
if($hours == && $mins 30) {
            
$period .= 's';
        }
        
//"And A Half" is here mostly for providing just a little more accuracy in fuzzying the time.
        
if($mins 30) {
            
$period "and a half ".$period;
        }
        return 
"$hours $period ago";
    }
    
//It's more than a day ago. Divide by 24 then floor it to get days. Then check if it's within the last week.
    
$days floor($time 24);
    
$hours floor($time - ($days 24));
    
//And now days and hours. Minutes could also be used, but I think something like "5 Days, 3 and a half Hours ago" is a bit much
    
if($days 7) {
        
$period "day";
        if(
$days 1) {
            
$period .= 's';
        }
        
//This part is again, for providing just a little extra accuracy in fuzzying the time.
        
if($hours >= 1) {
            
$period2 "hour";
            if(
$hours 1) {
                
$period2 .= 's';
            }
        return 
"$days $period$hours $period2 ago";
        }
        return 
"$days $period ago";
    }
    
//It's more than a week ago. Divide days by 7 to get weeks. Due to the design of the function, this would output something like "53 weeks, 3 days ago" if the date provided was a year, a week and 3 days ago. During development I never really anticipated needing it to do months or years.
    
$weeks floor($days 7);
    
$days floor($days - ($weeks 7));
    
$period "week";
    
$period2 "day";
    if(
$weeks 1) {
        
$period .= 's';
    }
    if(
$days 1) {
        
$period2 .= 's';
    }
    
//Again for accuracy.
    
if ($days 1) {
        return 
"$weeks $period ago";
    }
    return 
"$days $period2$weeks $period ago";
}
//By design, this only goes as far as weeks, but it could easily be expanded to months and years.
?>