PHP scheduled email alerts using preselected timezone - php

I've been searching alot and I can't seem to find a solution.
I have a PHP web page where I can schedule email alerts at specific times. I select the date and time of when the alert is to be sent. This is stored in MySQL table in UNIX format. I have a job that executes every 15 minutes and sends the emails if the date+time is in the past - this all works perfectly except I need to extend it for my USA colleagues. I am based in Ireland so I will need to manage the different timezones all across the US. I am planning on adding a select list of timezones that the user will have to select once they register...at least thats a start. Managing timezones is fine because I reckon all I need to do is minus the time different from the server time and then save the date time in unix format. DST is a different issue tho - does anyone have any ideas on how to overcome this?
I have read that using UTC as the base time but even if that is the case wont I still have the same issue?
Thanks a mil!

Your times are already in UNIX timestamp format so all you need is to calculate time difference (offset) of user. For example Ireland is in UTC/UTC+1 timezone. So all you need is to do the math like james_t mentioned in his comment. If you need user from Ireland to get an email in 9:00pm UTC+1 you have to send it in 8:00pm UTC. So what's an idea?
Allow users to select timezone which means they select offset from UTC. Keep it somewhere in database (your users table or some other table, doesn't matter).
Convert offset in seconds:
$delta_time = -1 * $offset * 3600
Then calculate your trigger-time:
$trigger_time = time() + $delta_time;
Now you have time when your email sender can fire in right moment depending on user's timezone settings.
For example:
$offset = 1; // summer in Ireland
$server_time = time(); // at the moment 1350509127
$delta_time = -1 * $offset * 3600; // -3600
$trigger_time = $server_time + $delta_time; // 1350505527
All you need is to compare $trigger_time with UNIX timestamp from your database and decide to send an email (or not).
Ofc, it's not bad idea to use PHP timezones instead of pure +/- offset and stay updated when DST changes apply on certain locations.
Make some test, this is not that hard.
This is just a general idea, not complete working solution.
Update:
To calculate time-difference in seconds between any two timezones you can use something like this:
function delta_offset()
function delta_offset($server_timezone, $user_timezone) {
$dt = new DateTime('now', new DateTimeZone($server_timezone));
$offset_server = $dt->getOffset();
$dt->setTimezone(new DateTimeZone($user_timezone));
$offset_user = $dt->getOffset();
return $offset_user - $offset_server;
}
To get an offset in seconds:
$server_tz = "Europe/London";
$user_tz = "America/New_York";
$offset = delta_offset($server_tz, $user_tz); // offset in sec.
Create some output:
$dt = new DateTime('now', new DateTimeZone('UTC'));
echo "<pre>UTC date/time: " . $dt->format('l, F jS, <b>H:i:s</b>') . "\n";
$dt = new DateTime('now', new DateTimeZone($server_tz));
echo "London date/time: " . $dt->format('l, F jS, <b>H:i:s</b>') . "\n";
$dt = new DateTime('now', new DateTimeZone($user_tz));
echo "New York date/time: " . $dt->format('l, F jS, <b>H:i:s</b>') . "\n\n";
echo "Time difference between London (UK) and New York (USA) is: <b>$offset_h</b> ($offset s)</pre>";
Output in browser (in moment of writing this post):
UTC date/time: Wednesday, October 17th, 22:32:27
London date/time: Wednesday, October 17th, 23:32:27
New York date/time: Wednesday, October 17th, 18:32:27
Time difference between London (UK) and New York (USA) is: -5:00 (-18000 s)
In this case offset is -5 hours (-18000 seconds) but it automatically changes if DST rules change for any of timezones given as function-arguments.
Delta-offset provides information how much earlier or later you have to send an email to user in different timezone and all you need now is to do simple +/- delta-offset with your email-sender's scheduler.
Hope this may help you to get right solution for your problem.
Update #2 - Example (theory)
Imagine this situation.
Your current server-time is X and its 7:00pm at the moment in Ireland. I live in Serbia and we have same DST rules but I’m one hour after (UTC+1/UTC+2). Difference between your and my time is +3600 seconds (1 hour).
Now you have to send an email to me in 10:00pm (it’s 9:00pm in Ireland).
Current time is X.
Delta-offset is -1 * +3600 = -3600 (delta-offset multiplied with -1).
Sending time on your location in 10:00 pm is X + 10800 (3 hours later).
Sending time on my location in 10 pm is X + 10800 + delta-offset = X + 7200 (2 hours later).
Formula to check if actual time is equal or greater than trigger-time (sending time) is:
current_timestamp >= trigger_timestamp + delta_offset
where delta-offset from delta_offset() function must be multiplied with -1 to use in formula.
Now you can send email when you want and be sure it will be sent using user's local time (ofc, if user timezone settings are correct).
Note: Difference from this example (Serbia - Ireland = +1 hour) is different during DST changes which means that 1 hour every year we're in same timezone (0 delta-offset), and one hour we have +2 hours delta-offset. This is possible because DST changes are applied 1 hour earlier in Serbia so when our time is changed +1 you have to wait 60 minutes before same change applies to Ireland-time *then we're +2) and same thing when we bring back clock to normal time (0 difference).

Related

Adding 2 different timestamp and dealing with PHP Datetime class

I'm building an application that shows specific times on a given day. This application is meant to serve ppl worldwide.
I do all the calculation with a TZ in an hour format (-4 / 2 / 9.5 / -1 ETC). (don't worry. the hour tz is after DST calculations)
Now, I would like to show the user his local time. due to dev reasons, i can use only the hour tz for this calculation.
after a lot of tries, i maneged to write a piece of code that seems to work. (tested it for few timezones, negetive and positive)
I am wondering if my code is ok? could i do it in a more efficent way? do this code support infinite date range?
here is the code:
static function current_local_time_zmanim($tz)
/*
* This function will get the number of hours off set (the time zone that Full_Zmanim_calculation() is using to make the calcukation) and will return the current local time and date.
*/ {
$tz= ($tz * 3600);// calculatoin: (hour offset(tz. can be -4 or 4) * 3600). eg: (-4*3600) or (3*3600)// converting the hour tz to TIMESTAMP
$date_utc = new DateTime(null, new DateTimeZone("UTC")); // current time in UTC.
$utctime= $date_utc->getTimestamp(); // current time in UTC TIMESTAMP
$date_utc->setTimestamp($utctime + ($tz));// keep in mind that tz can be either positive or negetive
$localtime= $date_utc->format('H:i');
echo "<br> local time: $localtime <br> ";
return $localtime;
}
What do you think?
Thanks!

Carbon Time Difference of Local Time and Server Time

I am using Laravel 4 and trying to calculate the difference of the Time on Server and the Time Save in Database in hours. Here is the code:
Time on Server=timeNowOnServer // 2016-02-03 19:05:43
Time saved in Database = setTime // 18:00:00
$timeNowOnServer = null;
$setTime = null;
$timeZone = $company->time_zone;
$company->save();
// My Time
$hour = substr($company->emp_auto_logout_time, 0, 2);
$setTime = Carbon::createFromTime($hour);
// Server Time Same as Mine
$timeNowOnServer = Carbon::now();
$timeNowOnServerSameAsMine = $timeNowOnServer->setTimezone($timeZone);
// Time Differnce Between SetTime and TimeOnServerSameAsMine
$timeDiff = $setTime->diffInHours($timeNowOnServerSameAsMine, $abs = false);
If Server Time is 14:00:00 for example and Set Time is 19:00:00. My time zone is GMT +5 Pakistan.
What I'm doing is, adding setting Server Time according to user time by giving time zone in the 3rd last line of the above given code.
When I use diffInHour it instead of giving me 0 it gives me -5 or 5. It means it's useing UTC (Server Time) and that's why give wrong difference in hours.
Can someone please let me know where I'm wrong?
You're trying to diff time in different time zones. A time difference (interval) is an absolute value, it doesn't depend on time zone. One second is always one second, be it UTC or Europe/Moscow.
Try without time zone (to be correct - using default server's time zone)
$timeDiff = $setTime->diffInHours($timeNowOnServer, $abs = false);
Always calc intervals using timestamps or the same time zone (doesn't matter exactly which one) for both DT values.

Go over 24 hours in a date?

I am working on project (a Google Transit feed) where I am required to provide the times for each stop on a bus route in the following common format: 21:00:00 and so forth.
Problem is, if times continue past midnight for a given trip, they require it to continue the hour counting accordingly. They explain quite specifically that 02:00:00 should become 26:00:00 and 03:45:00 should become 27:45:00 etc.
I am baffled on how to display such with any of the date() or strtotime() functions.
The only thing I can think of in my particular situation would be to function match and replace any strings in my output between 00:00:00 and 04:00:00, as that would clearly mean (again, for me only) that these are trips originating before midnight, but I don't feel that's the correct way.
Well seeing as it's only displaying on the page, you can
firstly get your date from where ever
Let's say $date = 00:00:00
$exploded_date = explode(":", $date);
This takes $date and puts it into an array so
$exploded_date[0] is hh
$exploded_date[1] is mm
$exploded_date[2] is ss
Then what you can do is use ltrim() to remove the leading 0 from 00 to 04 $exploded_date[0] - This makes it comparable in the if statement I'll do after
if($exploded_date[0] <= 4) {
$exploded_date[0] = ltrim($exploded_date[0], "0");
$exploded_date[0] = $exploded_date[0]+24;
}
Then you can implode the array back together into one string
$date = implode(":", $exploded_date);
// if the hour is 00 to 04 it will come out as 24 to 28
// e.g. 24:35:30
echo $date;
Despite giving you an answer. It's a silly thing to be doing, but it's not your choice so here you go :)
The way you display something doesn't necesarily has to be the same way you store something.
I don't know how you calculate the times, but assuming you have a start date and time, and some interval, you could calculate the end time as follows:
date_default_timezone_set('Europe/London');
$start_datetime = new DateTime('2014-11-11T21:00:00');
$next_stop = new DateTime('2014-11-12T02:00:00');
echo $start_datetime->format('Y-m-d H:i'); // 2014-11-11 21:00
echo $next_stop->format('Y-m-d H:i'); // 2014-11-12 02:00
$interval = $start_datetime->diff($next_stop);
// display next stop: 2014-11-11 26:00
echo ($start_datetime->format('Y') + $interval->y) .'-'
. ($start_datetime->format('m') + $interval->m) .'-'
. ($start_datetime->format('d') + $interval->d) .' '
. ($start_datetime->format('H') + $interval->h) .':'
. ($start_datetime->format('i') + $interval->i);
What I'm doing: create the start date (& time) and the datetime of the next stop. With the DateTime::diff() function I'm calculating the difference, and then, only for display (!) I add up each year, month, day, hour and minute to the datetime year, month etc. of the next stop.
This way you can still store your dates and times in a way every human being and computer system will understand (because let's be honest; to represent a time as 27:45 PM is quite ridiculous...)
I don't know if you only want the hours to be added up and roll over the 24 hour, or also days in a month etc. It's up to you how you handle these cases. Good luck!

PHP Date / GMT Weirdness

Either I'm losing my mind, or I've not got the faintest idea what I'm doing. I'm leaning towards the latter.
I'm trying to convert this: 1316826000, which I'm pretty confident should be Sat, 24 Sep 2011 01:00:00 GMT
http://www.onlineconversion.com/unix_time.htm confirms this.
http://www.unixtimestamp.com/index.php tells me 09 / 23 / 11 # 8:00:00pm EST, so far so good. I happen to be in EST, this is the result I'd like to get back from PHP.
When I do date('l, M d, Y, h:ia', $iTime), I get: Friday, Sep 23, 2011, 12:00am, a full 20 hours off.
I've confirmed the server's time is correct using date('c'). date('c') output is: 2012-05-19T03:19:20+00:00. The server is in the central time zone, where it is currently 10:20pm. May 18.
echo date_default_timezone_get() outputs "GMT" (set somewhere else in the script using date_default_timezone_set('GMT'))
What am I missing? Nothing I've read so far can explain how I'm getting a result 20 hours behind what it should be. Were it an hour fast or slow, I could at least wrap my head around it being some sort of DST idiotry, but 20? Crazyness! Thanks for reading!
Check what your php.ini says for date.timezone.
In unix it is usually here: /etc/php.ini
Then use a proper timezone recognized by PHP:
http://www.php.net/manual/en/timezones.php
date.timezone = 'America/New_York'
Then reload your web server.
Unix time just means the number of seconds since epoch. Has nothing to do with timezones. Timezones simply add or subtract 1 hour (3600 seconds) from the unix time for each zone you move away from GMT.
An example:
$userTimezone = new DateTimeZone('America/New_York');
$gmtTimezone = new DateTimeZone('GMT');
$myDateTime = new DateTime('2014-01-22 11:44', $gmtTimezone);
$offset = $userTimezone->getOffset($myDateTime);
echo $offset;
That will output: -14400 or 4 hours. Which is the difference between New York and GMT
Using some Java code with the Joda-Time 2.3 library, as I don't know PHP…
long m = 1316826000L;
DateTime dateTimeUtc = new DateTime( m * 1000L, DateTimeZone.UTC );
DateTime dateTimeNewYork = dateTimeUtc.toDateTime( DateTimeZone.forID( "America/New_York" ) );
System.out.println( "dateTimeUtc: " + dateTimeUtc );
System.out.println( "dateTimeNewYork: " + dateTimeNewYork );
I can tell you that 1316826000 seconds from the beginning of 1970 UTC/GMT (Unix Epoch) is…
dateTimeUtc: 2011-09-24T01:00:00.000Z
dateTimeNewYork: 2011-09-23T21:00:00.000-04:00
So, as the commenter stated, it would be 8 PM in EST but EST was not in effect on that day. DST (Daylight Saving Time) (idiocy, as you correctly noted) was in effect until November 9 of that year (2011). So the time of day is pushed forward one hour, to 9 PM.
In GMT/UTC, that means 1 AM in the morning of the next day.
Standard time in east coast US is 5 hours behind UTC/GMT. With DST it is 4 hours behind UTC/GMT (one hour closer).
Where you got confused:
Your time format/conversion in incorrect.I can't help with that as I don't know PHP.
You should be using a competent date-time library for this kind of work.Date-time work is complicated, tricky, confusing, and error-prone.This question discusses possibilities of Joda-Time (for Java) sorts of libraries for PHP.
You used three-letter time zone codes. Avoid these.Those codes are neither standardized nor unique -- there are common duplicates. Instead, use proper time zone names. In your case of east coast US, "America/New_York". Furthermore, in this case you confused the time zone area and rules (east coast US) with a particular application of those rules (EST). Saying "America/New_York" means "whatever time zone rules were in effect on that date, whereas saying "EST" (if interpreted to mean Eastern Standard Time in US) means "UTC-05:00". So either (a) use a time zone name such as "America/New_York", or (b) use a specific offset such as "-05:00".

how to subtract two dates and times to get difference

i have to sent an email when a user register email contain a link that is become invalid after six hours
what i m doing when email is sent i update the db with field emailSentDate of type "datetime"
now i got the curent date and time and has made to the same formate as it is in db now i want to find that both these dates and time have differenc of 6 hours or not so that i can make link invalid but i donot know how to do this
my code is look like this i m using hardcoded value for db just for example
$current_date_time=date("Y-m-d h:i:s");
$current=explode(" ",$current_date_time);
$current_date=$current[0];
$current_time=$current[1];
$db_date_time="2010-07-30 13:11:50";
$db=explode(" ",$db_date_time);
$db_date=$db[0];
$db_time=$db[1];
i do not know how to proceed plz help
<?php
//$now = new DateTime(); // current date/time
$now = new DateTime("2010-07-28 01:11:50");
$ref = new DateTime("2010-07-30 05:56:40");
$diff = $now->diff($ref);
printf('%d days, %d hours, %d minutes', $diff->d, $diff->h, $diff->i);
prints 2 days, 4 hours, 44 minutes
see http://docs.php.net/datetime.diff
edit: But you could also shift the problem more to the database side, e.g. by storing the expiration date/time in the table and then do a query like
... WHERE key='7gedufgweufg' AND expires<Now()
Many rdbms have reasonable/good support for date/time arithmetic.
What you can do is convert both of your dates to Unix epoch times, that is, the equivalent number of seconds since midnight on the 31st of December 1969. From that you can easily deduce the amount of time elapsed between the two dates. To do this you can either use mktime() or strtotime()
All the best.
$hoursDiff = ( time() - strtotime("2010-07-30 13:11:50") )/(60 * 60);
I'd rather work with a timestamp: Save the value which is returned by "time()" as "savedTime" to your database (that's a timestamp in seconds). Subtract that number from "time()" when you check for your six hours.
if ((time() - savedTime) > 6 * 3600)
// more than 6h ago
or
"SELECT FROM table WHERE savedTime < " . (time() - 6 * 3600)
This might be the solution to your problem -> How to calculate the difference between two dates using PHP?

Categories