Daylight Saving Time (DST) in CakePHP - php

I'm creating a web application using cakephp 1.2.6. There is a functionality that I need to save the time that user is entered in GMT format. I'm using below method to do this.
function convertDateTimeToGMT($dateTimeStr,$fromTimeZone, $format = 'Y-m-d H:i:s') {
if (empty($dateTimeStr))
return $dateTimeStr;
else if (empty($fromTimeZone))
return $dateTimeStr;
else {
// Inverse the + or minus. Decimal value should be passed
//$timeHelper = new TimeHelper();
$newTZ = -1 * $fromTimeZone;
return $this->format($format, $dateTimeStr, null, $newTZ) ;
}
}
function format($format = 'd-m-Y', $date, $invalid = false, $userOffset = null) {
$date = $this->fromString($date, $userOffset);
if ($date === false && $invalid !== false) {
return $invalid;
}
return date($format, $date);
}
function fromString($dateString, $userOffset = null) {
if (empty($dateString)) {
return false;
}
if (is_int($dateString) || is_numeric($dateString)) {
$date = intval($dateString);
} else {
$date = strtotime($dateString);
}
if ($userOffset !== null) {
return $this->convert($date, $userOffset);
}
return $date;
}
function convert($serverTime, $userOffset) {
$serverOffset = $this->serverOffset();
$gmtTime = $serverTime - $serverOffset;
$userTime = $gmtTime + $userOffset * (60*60);
return $userTime;
}
convertDateTimeToGMT($dateTimeStr,$fromTimeZone, $format = 'Y-m-d H:i:s') is the method that I'm calling in my code to pass the date time and time zone. I have a combo box of time zones and if user select time zone as "Pacific" it will pass the -8 as the value of $fromTimeZone. But because of the DST this can be changed.
So is there any way in cakephp to find the up to date time zone values automatically and convert the time to GMT?

Once you know the timezone of the user you can get its offset as follows:
$est_tz = new DateTimeZone('America/New_York');
$d = new DateTime("now", $est_tz);
$offset = $est_tz->getOffset($d);

Related

Calculating the php current time by timezone

Background
I am making some updated to a PHP application that is very old. In the application there was an error being thrown because the use of a depreciated function mktime(). I updated this function across the application with time() instead. Once I did this I noticed that when the local time for a user which is calculated by their zip code is displayed, it is one hour behind the actual local time.
I have tracked the time calculation to a function which is below. The time is passed into the value of, $client["localtime"]
Example Code
if (isset($time) && $time) {
$utc_str = gmdate("M d Y H:i:s", time());
$utc = strtotime($utc_str);
if (isset($tznames[ $time["timezone"] ])) {
$client["timezone"] = $tznames[ $time["timezone"] ];
} else {
$client["timezone"] = "Unknown";
}
if ($time["daylightsavings"] == "Y" && date("I")) {
$time["timezone"]--;
}
$client["localtime"] = date("g:ia", $utc - ($time["timezone"] * 3600));
} else {
$client["localtime"] = "Unknown";
$client["timezone"] = "Unknown";
}
Question
Why is this showing the local time for the client's timezone behind by 1 hour and what must I do to fix it?
if (isset($time) && $time) {
$utc_str = gmdate("M d Y H:i:s", time());
$utc = strtotime($utc_str);
if (isset($tznames[$time["timezone"]])) { $client["timezone"] = $tznames[$time["timezone"]]; }
else { $client["timezone"] = "Unknown"; }
if ($time["daylightsavings"] == "Y" && date("I")) { $time["timezone"]--; }
// print_r(($time["timezone"] * 3600).",".$client["timezone"].",".$time["timezone"].",".$utc_str.",".$utc);
$client["localtime"] = date("g:ia", $utc - ($time["timezone"] * 3600 - 3600));
} else { $client["localtime"] = "Unknown";
$client["timezone"] = "Unknown";}
Check the above code I have subtracted the 3600 from so that it show 1hour late please check if it will work
you can use this function
function convertTimeByTimezone($datetime,$timezone='Asia/Kolkata') {
$given = new DateTime($datetime, new DateTimeZone("UTC"));
$given->setTimezone(new DateTimeZone($timezone));
$output = $given->format("Y-m-d H:i:s");
return $output;
}
You can use this code:
$date = new DateTime("now", new DateTimeZone('Australia/Adelaide'));
echo 'Australia/Adelaide: '.$date->format('Y-m-d H:i:s');
$date1 = new DateTime("now", new DateTimeZone('America/Chicago'));
echo 'America/Chicago: '. $date1->format('Y-m-d H:i:s');

PHP detect if between specified date and now() matched specified condition

I want to know how to detect if a date range matched specified condition:
Expected results:
<?php
$start_date1 = '2016-05-06 00:00:00';
$start_date2 = '2016-01-06 00:00:00';
$result1 = is_date_range_exceeds_3_months($start_date1);
$result2 = is_date_range_exceeds_3_months($start_date2);
//lets say 'now' is '2016-06-06 00:00:00'
//Expected result of $result1 = false
//Expected result of $result2 = true
?>
(Please make correction to my question as I think this question is not in correct format/words)
Thanks!
You could use DateTime for this.
function is_date_range_exceeds_3_months($strDate)
{
$userDate = new \DateTime($strDate); // #todo: Check if is valid
$checkDate = new \DateTime(); // By default date seed is now
$checkDate->modify('+3 months'); // Set period
if($userDate > $checkDate) {
return true;
} else {
return false;
}
}
This is just a tip, sorry if it contains some typos.
Edit by OP:
function is_date_range_exceeds_x_months($month_limiter, $start_date) {
$userDate = new DateTime($start_date); // #todo: Check if is valid
$userDate = $userDate->format('Y-m-d H:i:s');
$checkDate = new DateTime(); // By default date seed is now
$checkDate->modify('-' . $month_limiter . ' months'); // Set period
$checkDate = $checkDate->format('Y-m-d H:i:s');
if ($userDate < $checkDate) {
return true;
} else {
return false;
}
}
<?php
$start_date1 = '2016-05-06 00:00:00';
$start_date2 = '2016-01-06 00:00:00';
$result1 = is_date_range_exceeds_3_months($start_date1);
$result2 = is_date_range_exceeds_3_months($start_date2);
//lets say 'now' is '2016-06-06 00:00:00'
function is_date_range_exceeds_3_months($start_date)
{
$lastdates=date('Y-m-d H:i:s', strtotime('-3 month'));
$current_dates=date("Y-m-d H:i:s");
echo 'currentdate'.$current_dates.'<br/>';
echo 'Lasytdate'.$lastdates.'<br/>';
if (($start_date > $lastdates) && ($start_date < $current_dates))
{
return true;
}
else
{
return false;
}
}
//Expected result of $result1 = false
//Expected result of $result2 = true
?>

Collect data from last 5 days in MySQL

I have following code
$date = date("Y-m-d");
public function ip2_exists() {
global $db,$date;
$code = $db->select("imp","id",array("date"=>$date,"ip"=>$this->ip()));
if($code->num_rows<1){
return false;
}
else {
return true;
}
}
It collects the current day data and it works fine. But I want to collect the last 5 days date.
How to do that in php?
Try:
$date = date("Y-m-d");
public function ip2_exists()
{
global $db,$date;
// Used to keep count track
$countDays = 0;
// Default return of true
$checkedData = true;
while($countDays < 5)
{
$code = $db->select("imp","id",array("date"=>$date,"ip"=>$this->ip()));
if($code->num_rows < 1)
{
$checkedData = false;
}
$countDays++;
$date = date("Y-m-d", strtotime( $date." -1 day"));
}
return $checkedData;
}

check upcomming birthday in a week 2 week or in a month using php

how to check is birthday is in this week,2week,or in month i have used below code to check but it return wrong calculation.
public function CountDown($birthdate, $days=7)
{
list($y,$d,$m) = explode('/',$birthdate);
$today = time();
$event = mktime(0,0,0,$m,$d,$y);
$apart = $event - $today;
if ($apart >= -86400)
{
$myevent = $event;
}
else
{
$myevent = mktime(09,0,0,$m,$d,$y);
}
$countdown = round(($myevent - $today)/86400);
if ($countdown <= $days)
{
return true;
}
return false;
}
Try this:
function CountDown($birthdate, $days=7)
{
# create today DateTime object
$td = new DateTime('today');
# create birth DateTime object, from format Y/d/m
$bd = DateTime::createFromFormat('!Y/d/m', $birthdate);
# set current year to birthdate
$bd->setDate($td->format('Y'), $bd->format('m'), $bd->format('d'));
# if birthdate is still in the past, set it to new year
if ($td > $bd) $bd->modify('+1 year');
# calculate difference in days
$countdown = $bd->diff($td)->days;
# return true if day difference is within your range
return $countdown <= $days;
}
demo
This worked for me
class Birthday{
public function CountDown($birthdate, $days=7)
{
list($y,$d,$m) = explode('/',$birthdate);
$today = time();
$event = mktime(0,0,0,$m,$d,$y);
$apart = $event - $today;
if ($apart >= -86400)
{
$myevent = $event;
}
else
{
$myevent = mktime(09,0,0,$m,$d);
}
$countdown = round(($myevent - $today)/86400);
if (($countdown <= $days))
{
return true;
}
return false;
}
}
$bday = new Birthday;
$count = $bday->CountDown("1969/16/11"); //today is 2014/14/11
var_dump($count); //returns true.
I just removed the year from the mktime() in $myevent. This changed the answers to be accurate.
The other way that it was being done made $countdown to be a huge negative number.

Timezone conversion in PHP with DateTime

I found some solutions recently and decided to go with this one so I created following method within one of my classes:
public static function date($format, $time = false, $from_timezone = false, $to_timezone = false) {
if (!$time) {
$time = time();
}
if (($from_timezone === $to_timezone) || (!$from_timezone || !$to_timezone)) {
return date($format, $time);
}
$from_tz = new DateTimeZone($from_timezone);
$to_tz = new DateTimeZone($to_timezone);
$dt = new DateTime();
$dt->setTimezone($from_tz);
$dt->setTimestamp($time);
$offset = $to_tz->getOffset($dt);
return date($format, $dt->format('U') + $offset);
}
Then I did a simple test - I converted datetime to some other timezone, and then convert the result back to the original timezone with expectations to get the original datetime.
$format = 'Y-m-d H:i:s';
$initialtime = '2013-06-13 12:00:00';
echo $initialtime;
echo '<br/>';
$convtime = TimezoneLib::date($format, strtotime($initialtime), 'Canada/Atlantic', 'Europe/Prague');
echo $convtime;
echo '<br/>';
echo TimezoneLib::date($format, strtotime($convtime), 'Europe/Prague', 'Canada/Atlantic');
die();
This is the output
2013-06-13 12:00:00 // Original
2013-06-13 14:00:00 // Converted
2013-06-13 11:00:00 // Converted to original timezone
Why dont they match? What am I missing? Thank you.
UPDATE
I am still unable to get matching dates even after removing strtotime. I found out that default timezone also affected DateTime objects. I came up with this:
<?php
class TimezoneLib {
public static $defaultSystemTimezone;
public static function init() {
self::$defaultSystemTimezone = date_default_timezone_get();
}
public static function date($format, $time = false, $from_timezone = false, $to_timezone = false) {
self::switchSystemTimezone($from_timezone);
if (!$time) {
$time = time();
}
if (($from_timezone === $to_timezone) || (!$from_timezone || !$to_timezone)) {
return date($format, $time);
}
$from_tz = new DateTimeZone($from_timezone);
$to_tz = new DateTimeZone($to_timezone);
$dt = new DateTime($time, $from_tz);
self::switchSystemTimezone($to_timezone);
$offset = $to_tz->getOffset($dt);
$convertedDate = date($format, $dt->format('U') + $offset);
self::restoreSystemTimezone();
return $convertedDate;
}
public static function switchSystemTimezone($timezone_identifier) {
return date_default_timezone_set($timezone_identifier);
}
public static function restoreSystemTimezone() {
return date_default_timezone_set(self::$defaultSystemTimezone);
}
}
TimezoneLib::init();
$format = 'Y-m-d H:i:s';
$initialtime = '2013-06-13 12:00:00';
echo $initialtime;
echo '<br/>';
$convtime = TimezoneLib::date($format, $initialtime, 'Canada/Atlantic', 'Europe/Prague');
echo $convtime;
echo '<br/>';
echo TimezoneLib::date($format, $convtime, 'Europe/Prague', 'Canada/Atlantic');
die();
With following output
2013-06-13 12:00:00
2013-06-13 19:00:00
2013-06-13 11:00:00
Create a new DateTime object instead than using strtotime:
$date = new DateTime('your_date_here', DateTimeZone object here);

Categories