Friday, August 31, 2007

date class update

I hadn't used the class before i posted it, stupid me, therefore i wasn't aware of the problem inserting the custom dateformat in a sql statement.

Mysql formats the dates as following yyyy-mm-dd hh:mm:ss so i had to convert the custom format into the database format. As you can see the added function dbformat is pretty simple leaving room for self formatted date strings.

In the interface functions i call the dbformat function and that gets the class up and running.




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

/**
*
* interface functions
*
*/

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

function getstr($str,$format = 'YmdHis', $date = null)
{
$date = (!isset($date))?$this->timestamp('db'):$this->dbformat($date);
$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 dbformat($date)
{
if(strlen($date) == 14)
{
$year = substr($date,0,4);
$month = substr($date,4,2);
$day = substr($date,6,2);
$hour = substr($date,8,2);
$min = substr($date,10,2);
$sec = substr($date,12,2);
$date = $year.'-'.$month.'-'.$day.' '.$hour.':'.$min.':'.$sec;
}
return $date;
}

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;
}
}
?>


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.