I'm working on a PHP solution for a radio station at the moment that requires me to determine whether the current time ("H:I" format) is between a set time frame.
The schedule comprises of intervals of 2 hours (starting at either 12midnight or 1am). This schedule is changeable dependent on a user selected timezone (or default setting).
The issue I'm having is determining whether the current time is between any of these times. For example, whether 2am is between 00:00 and 02:00, 04:00 etc.
Ultimately, I want to highlight the timeframe in which the current time falls.
I apologise if I'm being unclear in anything I've put, and I can explain further if necessary.
Use DateTime and DateInterval classes: http://hu1.php.net/datetime . I don't think different day and timezone is an issue in them...
Related
Introduction to my website
My website is for visitors in Korea(AKA Republic of Korea).
And the server for My website is in the United States of America.
And PHPMyAdmin displays EDT when it runs a query SELECT ## system_time_zone.
Structure of my website
When I first uploaded my website to this server in October this year, I checked the DB time.
And it seemed that there was a time difference of 13 hours with Korea. So I added 3600 * 13 seconds to DB time(without setting timezone) as follows.
const Offset = 3600 * 13;
$SelectNow = $PDO->prepare('SELECT DATE_ADD(NOW(), INTERVAL '.Offset.' SECOND)');
$SelectNow->execute() or exit;
$DbNow = $SelectNow->fetchColumn();
My website takes $DbNow as above and uses it in various situations.
For example, in the posting situation, enter $DbNow in the datetime field of the INSERT INTO query as follows:
$WriteNote = $PDO->prepare('INSERT INTO table_note(my_datetime, my_contents) VALUES("'.$DbNow.'", :my_contents)');
$WriteNote->bindValue(':my_contents', $my_contents, PDO::PARAM_STR);
$WriteNote->execute();
The problem situation
One day in November of this year, when I wrote a post and checked the date field(my_datetime) of the post, I got an additional time difference of one hour with Korea.
Apparently, at the end of October, I corrected the time difference of 3600 * 13. And then I confirmed that it matches the Korean time. However, in November, There is a time difference of one hour!
Guess the cause
It seems that US summer time is being applied to the DB server of my website. Did I guess right?
My question
1) How can I solve this time difference fundamentally?
Is it correct to convert DB time to KST?
Or is it the correct way to convert to UTC and then added 3600 * x to UTC?
2) Even though the problem is resolved, some of the existing data in my DB has a time difference of one hour with Korean time.
What query do I use if I want to select the data with a time difference?
And how much more or subtract it from the data to get rid of the 1 hour time difference?
Use UTC to store time in Database.
change your queries to insert with UTC datetimes.
Use external libraries to convert UTC to respective timezones.
(below are the my personal recommendation.)
There may be best of it.
PHP : Carbon
Javascript : Moment, moment timezone.
No, it takes timezone of Database server resides in.
little manual verification, or create a job to change all dates in UTC.
Edit:
http://carbon.nesbot.com/docs/
I mean you can create a script and run with cron job.
I have a MySQL database containing details of shops in different time zones. The timezone of each store is stored in iana format and the MySQL datetimes are stored in UTC.
I wish to execute some php code at the end of the day for each shop.
This is how I am thinking to approach this but is there a better way?
Set a cron to run hourly at xx:59:59.
Get the current date at the top of the php script. Is the script guaranteed to get the correct date at 23:59:59?
Use SQL query to return all shops that are at the end of the current day. I'm not sure how to check this in the query?
Perform the end of the day processing on those stores.
You can run an hourly cron job any time you wish.
Why do you need the date here? You wrote that you're interested in the servers, which are at 23:59:59 localtime, so time is relevant, I think, not the date. Also, if your details server is very busy, your script might run too late and get the next day's date.
If IANA time zone format means offset to UTC, you could simply look for shops having a timezone like
24 - current time(UTC) +/- DST
Negative timezone offsets work similar, e.g. 24 + offset. So timezone offset -01:00 would become +23:00
Nothing to say here.
I need an 'is open now' php function on a site I am building. Looking at a previous question, I have built my mysql table:
hours_id INT NOT NULL,
loc_id INT NOT NULL,
dow TINYINT NOT NULL,
open_time TIME NOT NULL,
close_time TIME NOT NULL,
Then using:
"SELECT open_time, close_time
FROM opening_hours
WHERE dow=dayofweek(curdate())
AND loc_id=:loc_id"
I can then work out if it is open or not. The product I am building is global and I will need the 'open now' to be related to the timezone the location is in, not the server location or the viewers location.
I am already storing the country code and lat/lng of the location in a related db, so my thoughts are that I obtain the timezone from that, or provide a method for the user to select one, and then modify my SQL somehow.
Am I heading in the right direction? What would your method be?
Read about time zone support in MySQL, and ensure your mysql database is configured with current time zone tables. Update regularly.
Associate each location with a named IANA/Olson time zone, such as "America/Los_Angeles", or "Europe/London". Refer to the list here. If you have lat/lon, you can look up the time zone via one of these methods.
Use the MySQL CONVERT_TZ function to convert the current UTC time to the specific zone. For example, CONVERT_TZ(UTC_TIMESTAMP(),'UTC','Asia/Tokyo')
Use the day-of-week and time of day of the converted time to check against the day and range in the location's entry.
Also, note that others may suggest taking the approach of only storing UTC in the database, or of converting all of the values to UTC before comparing against the "now" value. Either of those approaches can fail in edge cases, since the UTC day-of-week is not necessarily the same day-of-week as in each time zone.
One other approach that will work, but takes more effort, is to predetermine the specific UTC starting and stopping times for some amount of time in the future (at least to the next one, but perhaps further). Then you can scan this list with the UTC time. This works better at scale, when you have thousands or more individual entries to check. But at smaller scales, it's usually not worth the overhead.
Likewise, you could have a background process that just sets a "now open" flag on each record, but it would have to constantly be working against your database, and you could never check for other times than "now".
I am building a Time Clock application with PHP and Laravel 4.
My boss requires that he is able to pull and build different reports based on the data I store in the database for a Time Card record.
Right now I store a DateTime for clock in and clock out as well as a Timestamp for both those times as well into the Database.
I need to be able to Query the database and build reports for different Pay Periods for a user.
So for example I will store in another Database Table, records that will be for a User ID and will have different Pay Periods. So a Start day may be the 1st of the month and end date the 15th and that is 1 pay period (roughly 2 weeks) I am not sure the best way to store these records really.
Another will be the 16th of the month to the end of the month. So the end date would be different depending on how many days are in a month
I am not sure about the best way to define these Pay periods for a user. I can't simply say 1-15 and then 16-30 since the 30 would be a different number for each month.
Would appreciate any insight into how this could be done?
So I can build reports for any Pay Periods since not every user gets paid every 2 weeks it needs to be flexible so that I can define it on a per user basis
This question is more about the Logic instead of actual code.
Welcome to the wonderful world of Time and Attendance. You are touching the tip of the iceberg. You may find that purchasing a pre-packaged product may be easier than writing your own.
That said, I can offer you the following general advice:
Be very careful of your data types and how they are used, both in PHP and in MySQL.
You need to make sure you understand local time vs UTC, time zones, and daylight saving time. In general, you don't want to store local time unless you also store its offset from UTC. Otherwise you will have ambiguity around daylight saving time changes. This is important even if you only have one time zone to deal with.
When it comes to Pay Periods, the common types are:
Weekly
Bi-Weekly
Semi-Monthly
Monthly
Every X days starting from Y
In some systems, each individual pay period can be adjusted +/- a number of days from it's normal date. When doing so, the bordering period must also be adjusted to compensate.
You should start with business logic that can calculate the start and end date for a pay period given any particular date and time. You can then expand that to easily get the prior or next pay period.
You can store each pay period into it's own table, but it's not necessarily required. That will depend on a lot of specifics about your system internals.
Because a pay period is defined by dates, you have the "Whose Day is it?" problem. It might be the day as defined by the company, or if employees are in different time zones, then it might be the "logical day". If you only have one time zone to deal with then, you are lucky in this regard.
When comparing against the pay period, use half-open intervals, [start, end). In other words:
periodStart <= punchTime < periodEnd
or likewise
periodStart <= punchTime && periodEnd > punchTime
The end of one period should be exactly the same as the start of the next. Don't try to define the end of the period at some silly value like 23:59:59.999...
As you can see, this is just the beginning. I hope this is useful to you. If you can narrow the focus of your question further, I'll be happy to help more. Otherwise, it's like asking for how to build an ERP system when you're not sure what structure to store inventory.
I think you are over thinking this. Let thte user define the start and end dates.
You will need the UserId, a timestamp (time in and time out) of the user and that should be about it.
I picture something like this:
UserId | DateIn | DateOut
On the page you could put put dropdowns (or if you want a nifty interface a datepicker that uses javascript) and allow the manager to pick a start and end date that he wants to choose.
So if he wants to see an employees time between Jan. 1 and Feb. 31 he can choose those as his start and end dates.
This will allow things to be very flexible, for example the manager can choose Feb 16 as start date and Feb 29 as end date. It makes sense to allow him to choose the data requirements so he can view whatever he wants.
EDIT:
An example from my comment below this post you could do something like:
$startDate = new DateTime();
$startDate->modify('first day of this month'); //or 16th for second part of bi-monthly
$startDate->format(#some date formatting as you need#);
$endDate = new DateTime();
$endDate->modify('last day of this month'); //or 15th for first part of bi-monthly
$endDate->format(#some date formatting as you need#);
If things are even less defined however you could always try doing special math. date('t') will give you the number of days in a month. I would refrain from using this unless your pay days are fixed such as paid every 6 days.
In general I would harness the power of the PHP DateTime class over using date() function. http://php.net/manual/en/class.datetime.php
I've looked through the other solutions on SO and none of them seem to address the timezone/dst issue in the following regard.
I am making calls to NOAA Tide Prediction API and NOAA National Weather Service API which require a time range to be passed for retrieving data. For each location in my database, I have the timezone as a UTC offset and whether daylight savings time is observed (either 1 or 0). I'm trying to format some dates (todays and tomorrow) to be what the LST (Local Standard Time) would be in it's own timezone so I can pass to these API's.
I'm having trouble figuring out how to know if a date, such as todays, is within the daylight savings time range or not.
Here is what I have so far:
// Get name of timezone for tide station
// NOTE: $locationdata->timezone is something like "-5"
$tz_name = timezone_name_from_abbr("", $locationdata->timezone * 3600, false);
$dtz = new DateTimeZone($tz_name);
// Create time range
$start_time = new DateTime('', $dtz);
$end_time = new DateTime('', $dtz);
$end_time = $end_time->modify('+1 day');
// Modify time to match local timezone
$start_time->setTimezone($dtz);
$end_time->setTimezone($dtz);
// Adjust for daylight savings time
if( $locationdata->dst == '1' )
{
// DST is observed in this area.
// ** HOW DO I KNOW IF TODAY IS CURRENTLY DST OR NOT? **
}
// Make call to API using modified time range
...
How can I go about doing this? Thanks.
You can use PHP's time and date functions:
$tzObj = timezone_open($tz_name);
$dateObj = date_create("07.03.2012 10:10:10", $tzObj);
$dst_active = date_format($dateObj, "I");
If DST is active on the given date, $dst_active is 1, else 0.
Instead of specifying a time in the call to date_create you can also pass "now" to receive the value for the current date and time.
However, like Jon mentioned, different countries within the same timezone offset may observe DST while others may not.
For each location in my database, I have the timezone as a UTC offset and whether daylight savings time is observed (either 1 or 0).
That's not enough information. There can be multiple time zones which all have the same standard offset, all observe DST, but perform DST transitions at different times. (Indeed, historically they may also start and stop observing daylight saving time for several years.)
Basically, your database should contain a time zone ID, not the offset/DST-true-or-false. (Assuming PHP uses the zoneinfo time zone database, a time zone ID is something like "Europe/London".)
EDIT: To find the offset of a given DateTime, you can call getOffset, which you can then compare with the standard time offset. But unless you have the definitive time zone ID, you will be risking getting the wrong zone.
Cillosis,
I hope you are not working with Java! I am and fought with time all the time. I also work with weather data. Most of the data I use is in local standard time (ignoring daylight saving time). I also need to use times from other time zones and found that Java kept reading my computer's time zone. I also kept running into deprecated classes. I came up with a solution that works. It is a bit of a kluge, so I have it heavily documented and it only exists in one function. My solution is relative time. I have set the local time to UTC. I am subtracting the GMT offset instead of adding it. I don’t really care about the actual times, all I care about is the difference between two times. It is working very well.
Good luck