PHP,Codeigniter:如何在Web应用程序中根据用户时区/位置设置日期/时间?

时间:2010-02-16 16:47:20

标签: php datetime codeigniter timezone

我刚刚意识到,如果我将特定记录添加到我的MySQL数据库中 - 它将具有服务器的日期/时间而不是特定用户以及它们所在的位置,这意味着我按日期搜索功能是无用的!因为当他们在时区中添加它而不是在服务器时区中添加时,他们将无法搜索。

Codeigniter中是否有一种方法可以全局设置特定于用户位置的时间和日期(可能使用其IP),并且每次调用date()或time()时都会使用用户时区。

  

我实际要求的是   可能是如何使我的应用程序   依赖于每个用户的时区?

也许最好将每个用户时区存储在他们的个人资料中并有一个标准时间(服务器时间),然后将时间转换为每个用户?

全部谢谢

8 个答案:

答案 0 :(得分:5)

听起来您需要做的是将系统中的所有日期和时间存储为UTC时间(以前称为GMT)。这是世界上所有事物都是通过调整来计算的基准时间。 (例如:中央时间距离UTC约-6小时)

在MySQL中,只要您的服务器和数据库配置了正确的时间和时区设置,您就可以使用UTC_TIMESTAMP()来获取当前的UTC时间。

在PHP中运行此命令将PHP的时间戳设置为UTC(您将在代码中运行此代码,因此将其放在每个页面或集中索引文件中):

date_default_timezone_set('UTC');

或者您可以直接进入PHP.INI并告诉它全局使用UTC时间。 (如果您在单个PHP安装上有多个网站,这可能无效。

然后在系统中的任何地方,您需要获得当前的UTC时间,您可以致电:

time();

然后,对于系统中的每个用户,您需要询问他们居住的时区,然后在显示时间时对该用户进行调整。因此,如果是UTC时间下午5:00,我居住在美国复活节(-5),那么时间将是5:00 - 5小时=中午12:00。

这可能是一个很长的过程,但是一旦你做到了,你的用户会发现它非常有用,特别是在国际上。

答案 1 :(得分:4)

我认为最简单的方法是为内部数据存储定义一个时区(服务器的时区或UTC),并在输出时根据用户的时区转换时间。

我不知道CodeIgniter所以我不能指出你正确的功能。一个突出时区的着名图书馆是Zend_Date:Working with Timezones我还没有使用过这些函数,但看起来很有希望。

但是,一旦你知道了用户的时区,就不难将一个自己的函数放在一起,在输出日期和/或时间时添加/减去偏移量。

可能相关的问题:

答案 2 :(得分:2)

以WordPress和phpBB等现有Web应用程序为例。每个用户都有自己的时区设置。

从用户收到内容时,使用Date Helper中的local_to_gmt()功能,然后使用gmt日期将内容保存到数据库中。获取数据时,您将获得gmt中的时间。获取用户的时区设置,然后显示该时区中的数据。

这样,您可以避免在两个时区之间进行计算。只需确保服务器的时间设置正确,因此您的所有数据都处于正确的gmt时间内。

更新:

最近我回顾了我工作的最后一个有时区问题的项目。在考虑了各种场景之后,以下是时区问题的解决方案:

  1. 现在已存储所有数据 使用服务器的时间。改变这一点 将花费时间并容易出错, 所以我就这样离开了。
  2. 用于将内容日期设置为特定的用户的新数据 日期和时间,我把它存储到2 柱。第一栏是存储 数据原样,用于显示 就是这样。第二栏将是一个 基于的重新计算日期 用户进入服务器的时区 时区。此列用于 WHERE语句(基于的过滤器 服务器日期)和ORDER (因为这个列的值全部在 相同的时区,这是服务器的 时区)。
  3. 这样,我只做1个时区计算,即将用户日期转换为服务器日期。为了显示,我根据服务器的日期时间显示日期。由于所有数据都存储在同一时区,因此数据可以按保存服务器日期值的列进行排序。

    对于已设置时区的用户,可以轻松重新计算数据库中的日期,以便在用户的时区中获取日期时间。顺便说一句,在我的应用程序中,我使用timeago jquery plugins显示日期。此插件需要ISO8601格式的时间(UTC时间)。 CodeIgniter中的local_to_gmt()函数可用于执行此操作。

答案 3 :(得分:1)

我认为重新计算用户的时间是更好的选择,因为它可以为您提供服务器上的标准化时间,即如果您需要查找某些内容,那么(从您的角度来看)一小时前,您将不会有与美国,亚洲和例如混乱澳大利亚时间。

只需询问他们的时区(通常选择该时区的主要城市),然后重新计算:)

或者,或者,您可以存储两个时间 - 一个用于比较,一个用于显示,因此您不会在服务器端进行太多计算。

另外,如果重新计算,您可以使用日期助手: http://ellislab.com/codeigniter/user-guide/helpers/date_helper.html

答案 4 :(得分:1)

显然,英国夏令时(夏令时)的飞跃在编程领域是一个很大的混乱,我确实陷入了混乱。

使用时区敏感系统时,我能找到的最佳解决方案(我会尝试连贯地解释)是:

  • Web服务器和数据库都应该在相同的计算机时区运行。我建议使用UTC,因为它是时区转换的基石。这将确保存储在数据库中的所有日期都是常量,并且不会跳过任何时间,例如夏令时之间的1小时跳转。
  • 在所有PHP脚本的顶部,使用date_default_timezone_set('Europe/London');和用户的特定时区。
  • 从用户提交的表单生成日期时,请使用gmmktime();确保创建的时间戳为UTC,并且不会被您设置的时区更改。
  • 显示日期时可以使用
  • date();,因为这会将时间戳转换为正确的时间,并考虑到您设置的时区。
  • 如果您确实需要以UTC格式显示日期,请使用gmdate();与您从数据库中获取或使用$gm_timestamp创建的gmmktime();

我已经写了一些PHP来帮助理解这种情况。

date_default_timezone_set('UTC');
$gmtime = gmmktime(2,0,0,03,29,2009);
$time = mktime(2,0,0,03,29,2009);
echo $gmtime.'<br />'.date('r',$gmtime).'<br />'.gmdate('r',$gmtime).'<br />';
echo $time.'<br />'.date('r',$time).'<br />'.gmdate('r',$time).'<br />';

date_default_timezone_set('Europe/London');
$gmtime = gmmktime(2,0,0,03,29,2009);
$time = mktime(2,0,0,03,29,2009);
echo $gmtime.'<br />'.date('r',$gmtime).'<br />'.gmdate('r',$gmtime).'<br />';
echo $time.'<br />'.date('r',$time).'<br />'.gmdate('r',$time).'<br />';

希望我做得很好,但我对此表示怀疑,因为我仍在努力解决这个问题。

<强>更新

很高兴我这样做了,因为我现在对用户输入的日期有疑问。

要获得用户输入的日期(考虑到他们的时区)以匹配数据库中的UTC对应日期,您应该通过mktime()。然后使用gmdate('U', $timestamp);获取真正的UTC时间戳。 (我认为)

<强> 实施例

从报告方面来看,用户正在使用“欧洲/伦敦”时区。在我们的PHP脚本开始时,我们调用date_default_timezone_set('Europe/London');,而数据库(以及其中的所有记录)仍然是UTC。

用户然后通过它发送,他们想要在25/03/2010 10:00到30/03/2010 14:00之间选择添加到数据库的书籍列表。然后PHP脚本通过mktime($hour, $minute, $second, $month, $day, $year)运行日期变量以生成正确的UTC时间戳。开始日期不会改变,但PHP知道结束日期在BST时区内,因此将时间戳更改为UTC。

当结果返回给用户时,date('r', $date_added)可用于向用户显示根据设置的时区将图书添加到数据库的日期。

此链接可能有助于了解其何时发生变化。 http://www.daylightsavingtime.co.uk/

答案 5 :(得分:0)

我使用了MySQL内置的时区转换。在数据库中,所有日期时间都存储为UTC。在选择查询中,我使用CONVERT_TZ转换为用户的时区。您可以指定时区代码或小时invervals,如:

SELECT CONVERT_TZ('2004-01-01 12:00:00','GMT','MET');
SELECT CONVERT_TZ('2004-01-01 12:00:00','+00:00','+10:00');

但是,问题是这不适合夏令时。这尤其令人沮丧,因为世界上许多地方要么不尊重夏令时,要么在不同的日期兑现它。因此,如果您安装timezone description tables,则可以使用自动占用夏令时的描述性名称,例如:

SELECT CONVERT_TZ('2004-01-01 12:00:00', 'UTC', 'US/Eastern');

答案 6 :(得分:0)

Codeigniter包含一个处理各种日期函数的帮助程序。

Codeigniter Date helper

命令gmt_to_local()可以帮助你......第三个参数是'daylight_saving'。

Takes a Unix timestamp (referenced to GMT) as input, and converts it to a localized timestamp based on the timezone and Daylight Saving time submitted. Example:
$timestamp = '1140153693';
$timezone = 'UM8';
$daylight_saving = TRUE;

echo gmt_to_local($timestamp, $timezone, $daylight_saving);

答案 7 :(得分:0)

将此行添加到应用程序文件夹/ config文件夹中的autoload.php:

$autoload['time_zone'] = date_default_timezone_set('Asia/Kolkata');