Saturday, August 25, 2007

mysql date functions for own timestamp format

Introduction

I recently got familiar with the limitations of the unix_timestamp. I had to make it possible to generate dates from before 1970. This was a real pain because i had used the normal date functions of php.

So i had to come up with something quick and my first thought was using the date functions of mysql. Mysql doesn't have the 1970 limitation so i was free to use any date possible.

Because i don't wanted to change all the datatypes of the fields containing dates i had to find a numeric timestamp. This was not so hard, YYYYMMDDHHMMSS gives me a date range from 10000101010101 to 99991231235959.

The code
I got used to have two functions to generate timestamps, date and strtotime. Because i wanted my functions in a class i had to use short names because no self respecting programmer want to type a lot, but they do it any way.
get and getstr seemed descriptive enough because i named the class date.

I made the class as a model class for code igniter because that's the framework i use nowadays for almost all my projects. But changing it to native php code is not going be to hard.
i only show the basic, alpha class here because i first want to test the more complex functions.



class Datemodel extends Model
{
function Datemodel()
{
parent::Model();
}

/**
*
* interface functions
*
*/

function get($format = 'YmdHis', $date = null)
{
if(!isset($date)){ $date = $this->timestamp('db'); }
return $this->format($date,$this->preformat($format));
}

function getstr($str,$format = 'YmdHis', $date = null)
{
if(!isset($date)){ $date = $this->timestamp('db'); }
$sign = substr($str,0,1);
$period = trim(substr($str,1));
return $this->get($format,$this->interval($date,$sign,$period));
}

/**
*
* helper functions
*
*/

function timestamp($type = '')
{
switch($type)
{
case 'db': $query = $this->db->query('select NOW() as ts'); break;
default: $query = $this->db->query('select NOW()+0 as ts'); break;
}
$row = $query->row();
return $row->ts;
}

function format($date,$format)
{
$query = $this->db->query('select date_format("'.$date.'","'.$format.'") as val');
$row = $query->row();
return $row->val;
}

function interval($date,$sign,$period)
{
switch($sign)
{
case '+': $query = $this->db->query('select date_add("'.$date.'", interval '.$period.') as val'); break;
case '-': $query = $this->db->query('select date_sub("'.$date.'", interval '.$period.') as val'); break;
}
$row = $query->row();
return $row->val;
}

function preformat($str)
{
$array = array('%','a','b','c','d','e','h','i','j','k','l','m','p','r','s','u','v','w','x','y','D','H','I','M','S','U','V','W','X','Y');
foreach($array as $char)
{
$str = str_replace($char,'%'.$char,$str);
}
return $str;
}
}
?>



As you can see the sql statements are very simple and for the format i made it possible to use the letter only format instead of the mysql format.

Future
This is only a basic, alpha class which should not be used on production sites.

i'm planning to make the class cross-database so it can be used everywhere and for now i'm testing a more complex method, diff, which takes care of date calculations. And the possibility for getstr and diff to be aware of weekends and vacations.

No comments: