Times and timezones

Not for 'how-to' coding questions but PHP theory instead, this forum is here for those of us who wish to learn about design aspects of programming with PHP.

Moderator: General Moderators

Post Reply
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

Times and timezones

Post by Ambush Commander »

I'm trying to make a very locale-aware website with respect to times and dates. Because I am only storing Unix timestamps, this is surprisingly difficult. Here are the requirements:

[*] Input times are Unix timestamps, with no extra information. This cannot be fudged.
[*] Timezones are location-specific; i.e. not EST or EDT, but America/New_York
[*] The current time should be displayed appropriately as EST or EDT, depending on the year
[*] The tricky part: past times on backdated entries should have a timezone appropriate for the time of the year they were posted. Even if it's EDT now, if it was originally posted as EST it should still display as EST.

Points 1 and 4 are slaying me. Is there any easy way to do this with PHP's timezone support?
User avatar
andyhoneycutt
Forum Contributor
Posts: 468
Joined: Wed Aug 27, 2008 10:02 am
Location: Idaho Falls

Re: Times and timezones

Post by andyhoneycutt »

If you're storing a timestamp for the record creation, you could easily just say something like:

Code: Select all

 
$was_dst = false;
if( date("I",$row['some_time']) ) // DST in effect
{
  // code here to switch your locale, or stored locale since
  // date() is only going to tell you if the local server thinks the
  // date is DST.
  if( $all_of_the_above_checks out ) $was_dst = true;
} 
return $was_dst;
 
As far as #1 goes, I'm not sure I see the problem with working with timestamps in this example. Any more info?
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Re: Times and timezones

Post by Christopher »

If you have a timestamp and a locale like "America/New_York" you should be able to convert the locale to UTC (all Unix system can do this) which would give you something like -5 hours (from GMT). You need to store that with the timestamp I suppose. Then you just do $timestamp - (-5 * 60 *60) to get the GMT. Once you get the timezone offset you can get to any other timezone.
(#10850)
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

Re: Times and timezones

Post by Ambush Commander »

Thanks for the replies.
As far as #1 goes, I'm not sure I see the problem with working with timestamps in this example. Any more info?
So this actually works reasonably well, albeit slightly clunky. (And heaven forbid there's a time-shift that's not daylight savings time related). The next step, then, is: given America/New_York and $dst == 1 or 0, what are the three letter codes for it? I could hard-code it (EST, EDT), but does timezone give me a facility to find this out (maybe timezone_transitions_get())? Also, that means I have to run the detection code on every output of a DateTime, which also kinda sucks. (maybe a subclass is in order?)

Any suggestions here?
If you have a timestamp and a locale like "America/New_York" you should be able to convert the locale to UTC (all Unix system can do this) which would give you something like -5 hours (from GMT). You need to store that with the timestamp I suppose. Then you just do $timestamp - (-5 * 60 *60) to get the GMT. Once you get the timezone offset you can get to any other timezone.
Ah; I am starting off with a UTC timestamp (that's what I thought Unix timestamp meant). The problematic part is getting it into the appropriate timezone.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Re: Times and timezones

Post by Christopher »

Ambush Commander wrote:Ah; I am starting off with a UTC timestamp (that's what I thought Unix timestamp meant). The problematic part is getting it into the appropriate timezone.
e.g., /usr/share/zoneinfo/America/New_York
(#10850)
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

Re: Times and timezones

Post by Ambush Commander »

That certainly isn't very portable ;-)
User avatar
andyhoneycutt
Forum Contributor
Posts: 468
Joined: Wed Aug 27, 2008 10:02 am
Location: Idaho Falls

Re: Times and timezones

Post by andyhoneycutt »

Ambush Commander wrote:The next step, then, is: given America/New_York and $dst == 1 or 0, what are the three letter codes for it?

Any suggestions here?
Take a look at this page. I'm thinking you could build a static object (an array I would suggest) based on the information on this page, flip the keys with the values, so you'd end up with the keys being "America/New_York" and the values being "EST" or whatever. That should give your abbreviations.

-Andy
ssssss
Forum Newbie
Posts: 17
Joined: Fri Aug 29, 2008 8:34 am

Re: Times and timezones

Post by ssssss »

I'm confused about a couple of things.

Aren't timestamps created based on the time zone set for the server? I think you have to specifically create a GMT time zone (using gmdate() or date_default_timezone_set() for example) or convert to get one. Correct me if I'm wrong here. If so, then all of your existing timestamps have time zone data, they're just all the same. They're the time zone set for your server.

Regarding number 2, I think if you've got the time zone and the timestamp (you have both), you can figure out whether it's an EST or EDT time. Use date('I'). That's a capital letter "i". Or see the date() documentation.

Regarding number 3, I'm pretty certain that that is the default behavior, based on the time zone set for your server.
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

Re: Times and timezones

Post by Ambush Commander »

So, part of your confusion results from the nomenclature, specifically, "timestamp". The timestamp I am referring to is called the Unix timestamp, which is basically the number of seconds since the Unix epoch (January 1, 1970, iirc). This value is completely timestamp independent, and you use a function like date() to get it into human readable form.

What you're talking about is the output of date(). The input is timezone independent, but the output can changed based on whether or not the server has a timezone set or not. gmdate() is date() with GMT set as the timezone.

So what I'm trying to do is I'm trying to output a time as either EST/EDT, and the current proposed solution is to run the Unix timestamp through date() once to determine if it's DST or not, and then set the appropriate timezone and do it again. Clunky to say the least.
ssssss
Forum Newbie
Posts: 17
Joined: Fri Aug 29, 2008 8:34 am

Re: Times and timezones

Post by ssssss »

You're right. I was thinking that time() was time zone dependent like date(). That is not the case.

So you've got GMT timestamps. Do you have more than one time zone you're working with, or is it just NYC?

I think if you've got the time zone set, that date() will handle the Daylight savings stuff for you. EST/DST is location and time specific, and I'm pretty sure that given the time and location (time zone), PHP will figure it out for you and display the correct time.

Code: Select all

date_default_timezone_set('America/New_York');
echo "Eastern - ", date_default_timezone_get(), "\n";
echo time(), " = ";
echo date('g:i A, I'), "\n\n";
 
date_default_timezone_set('America/Chicago');
echo "Central - ", date_default_timezone_get(), "\n";
echo time(), " = ";
echo date('g:i A, I'), "\n\n";
 
date_default_timezone_set('America/Denver');
echo "Mountain - ", date_default_timezone_get(), "\n";
echo time(), " = ";
echo date('g:i A, I'), "\n\n";
 
date_default_timezone_set('America/Phoenix');
echo "Mountain (Arizona / No Daylight Savings Time) - ", date_default_timezone_get(), "\n";
echo time(), " = ";
echo date('g:i A, I'), "\n\n";
 
date_default_timezone_set('America/Los_Angeles');
echo "Pacific - ", date_default_timezone_get(), "\n";
echo time(), " = ";
echo date('g:i A, I'), "\n\n";
 
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

Re: Times and timezones

Post by Ambush Commander »

Right. The problem is that when you use date with the second parameter (an integer timestamp), the displayed timezone is the current one, so you get times like 3:00 EDT on a date when DST was not in effect.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Re: Times and timezones

Post by Christopher »

Right, but you can just use getdate() to see if the month/day is DST or not, and then display EST or EDT. I think I am missing something in this thread...
(#10850)
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

Re: Times and timezones

Post by Ambush Commander »

No, you're right. I slightly don't like doing that because: 1. it's hacky and 2. I need to know the DST and non-DST timezone names in advance, or do some tricky stuff with PHP's tz databases.
ssssss
Forum Newbie
Posts: 17
Joined: Fri Aug 29, 2008 8:34 am

Re: Times and timezones

Post by ssssss »

Do actually want anything more than the "T" format from date()?

Code: Select all

echo date('g:i A, T', $ts)
That will display the EST/EDT or whatever for the time zone you want, as long as you know what time zone you want, and you set it first:

Code: Select all

date_default_timezone_set('America/New_York');
If you don't know what time zone you want to display, PHP ain't going to know either. Is that the challenge?

PHP WILL know whether the time is DST or not depending on the time zone you set. So I don't understand your comment:
The problem is that when you use date with the second parameter (an integer timestamp), the displayed timezone is the current one, so you get times like 3:00 EDT on a date when DST was not in effect.
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

Re: Times and timezones

Post by Ambush Commander »

Well, what do you know! Apparently, T does account for EST/EDT according to the timezone :o) A little more research showed that the reason why I've been complaining about this is that when you new DateTime('@12938284'), it ignores the default timezone and sets it as UTC, so you have to setTimezone the object.

Thanks ssssss; this topic is resolved. :-D
Post Reply