【问题标题】:PHP, Codeigniter: How to Set Date/Time based on users timezone/location globally in a web app?PHP,Codeigniter:如何在 Web 应用程序中根据用户时区/位置全局设置日期/时间?
【发布时间】:2011-01-17 11:45:05
【问题描述】:

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

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

我真正想要的是 大概如何制作我的申请 取决于每个用户的时区?

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

谢谢大家

【问题讨论】:

  • @Abs - 我在下面的帖子介绍了如何使 PHP 时区中的 Web 应用程序敏感,而不管您使用的 MVC 是什么。我所做的是采用我在下面提到的原则并编写了一个名为utc_helper 让我更容易使用 utc_now() 获取当前时间或使用 utc_convert($time, $from_zone, $to_zone) 转换时间。如果您对此有任何疑问,请告诉我,我很乐意为您提供帮助。

标签: php datetime codeigniter timezone


【解决方案1】:

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

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

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

date_default_timezone_set('UTC');

或者您可以直接进入 PHP.INI 并告诉它在全球范围内使用 UTC 时间。 (如果您在一次安装 PHP 时有多个网站,这可能不起作用。

然后在系统中任何需要获取当前 UTC 时间的地方都可以调用:

time();

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

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

【讨论】:

    【解决方案2】:

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

    我不了解 CodeIgniter,因此无法为您指出正确的功能。 Zend_Date 是一个著名的时区感知库:Working with Timezones 我还没有使用过这些函数,但它们看起来很有希望。

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

    可能相关的问题:

    【讨论】:

    • 你是第一,啊! :]
    【解决方案3】:

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

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

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

    更新:

    最近我回顾了我从事的最后一个项目,该项目存在时区问题。在考虑了各种情况后,以下是时区问题的解决方案:

    1. 现在已经存储了所有数据 使用服务器的时间。改变这个 将需要时间并且容易出错, 所以我就这样离开了。
    2. 对于来自将内容日期设置为某个特定的用户的新数据 日期和时间,我将它存储到 2 柱子。第一列是存储 数据原样,用于显示 照原样。第二列将是 基于日期重新计算 用户的时区到服务器的 时区。该列用于 WHERE 声明(过滤基于 服务器日期)和ORDER (因为该列的值全部在 相同的时区,这是服务器的 时区)。

    这样,我只做1个时区计算,就是把用户日期转换成服务器日期。对于显示,我根据服务器的日期时间显示日期。由于所有数据都存储在同一时区,因此可以按保存服务器日期值的列对数据进行排序。

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

    【讨论】:

      【解决方案4】:

      显然,跳到英国夏令时(夏令时)是编程界的一大困惑,而我确实陷入了这种困惑。

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

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

      我写了一点 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。

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

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

      此链接可能有助于了解何时更改。 http://www.daylightsavingtime.co.uk/

      【讨论】:

        【解决方案5】:

        我认为重新计算用户的时间是更好的选择,因为它为您提供了服务器上的标准化时间,即,如果您需要查找一些事情,那发生在一个小时前(从您的角度来看),您不会有与美国人,亚洲人和例如澳大利亚时间。

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

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

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

        【讨论】:

          【解决方案6】:

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

          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');
          

          【讨论】:

            【解决方案7】:

            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);
            

            【讨论】:

              【解决方案8】:

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

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

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2015-08-29
                • 2013-05-29
                • 1970-01-01
                • 1970-01-01
                • 2011-11-26
                • 2017-06-23
                • 2011-10-14
                相关资源
                最近更新 更多