我已经找了几个小时了,看看在php/mysql web应用程序中使用时区的最佳方法是什么,很难找到一个明确的答案。根据我迄今为止所学,最好将每个人的资料以UTC格式存储在数据库中(如果我错了,请纠正我)。
当一个用户注册时,我会向他们询问那里的时区,然后将其存储在那里。此格式为下拉菜单:
1
| <option value ="Europe/London">(GMT ) Greenwich Mean Time : London </option > |
我正在构建的应用程序将允许用户在未来设置人员安排(会议),就像日历一样。很明显,在一年的时间里,不同的时区有不同的夏令时,你知道我该如何应付吗?
假设一个来自英国的用户在2013年1月24日下午3:00安排了一个会议,并邀请了一个住在加利福尼亚的人参加这个会议,我如何才能让美国人在他/她的时区看到这个会议,而英国用户在他/她的时区看到这个会议?(请注意,两个用户都已注册并设置了时区)。
有没有人对此有明确的解释,也许还有一些例子?或者可以指给我在哪里能找到它?
谢谢
- 向用户显示时间和时区信息的可能副本(什么,不是如何显示)或stackoverflow.com/questions/1285523/&hellip;
- 你知道,UTC(以前叫格林尼治标准时间)和伦敦当地时间不一样。伦敦遵守夏令时。
- 我知道(我住在英国),应该对夏令时也更清楚些。每次我想我几乎要把这些分类,DST似乎总是挡道而行:)
我在一年多前为一个私人喷气机操作员编写的PHP/MySQL应用程序中广泛地处理了这种情况。在这两个平台中,处理时区有不同的策略,但我将解释我是如何做到的。我将mysql服务器设置为utc,并在用户在用户配置文件注册过程中指定的时区中运行每个php脚本。
mysql和php(php 5.2及更高版本)都具有本机日期时间数据类型。mysql的datetime是一种原始数据类型,而php 5.2及更高版本提供了内置的datetime类。mysql datetime数据类型不包括时区的元数据,但php datetime对象始终包括时区。如果php datetime构造函数没有在第二个参数中指定可选时区,则php datetime构造函数使用php环境变量。
MySQL和PHP在配置文件中都设置了默认时区。MySQL使用配置文件中为每个DB连接设置的日期时间,除非用户在使用命令SET time_zone = [timezone];启动连接后指定了不同的时区。php还使用服务器配置文件中设置的时区为每个脚本设置一个时区环境变量,在脚本启动后,可以使用php函数date_default_timezone_set()覆盖此环境变量。
php datetime类有一个名为timezone的属性,它是php datetimezone对象。DateTimeZone对象是使用精确时区的字符串指定的。时区列表是全面的,在世界各地有数百个单独的时区。PHP时区将自动计入夏令时。
当用户在Web应用程序中生成日期时间时,在用户配置文件的时区中构造一个php-datetime对象。然后使用setTimezone方法将datetime对象修改为UTC时区。现在您有了以UTC表示的用户日期时间,并且可以将该值存储在数据库中。使用datetime format方法将数据表示为MySQL接受的格式的字符串。
因此,用户生成一个datetime,并在用户指定的时区中生成一个php datetime对象:
1 2 3 4 5 6 7 8
| // set using an include file for user profile
$user_timezone = new DateTimeZone('America/New_York');
// 1st arg in format accepted by PHP strtotime
$date_object1 = new DateTime('8/9/2012 5:19 PM', $user_timezone);
$date_object1->setTimezone(new DateTimeZone('UTC'));
$formated_string = $date_object1->format('Y-m-d H:i:s');
$query_string="INSERT INTO `t_table1` (`datetime1`) VALUES('$formated_string')"; |
从数据库中检索值时,请使用UTC构造,然后转换为用户的时区。
1 2 3 4
| $query_string="SELECT `datetime1` FROM `t_table1`";
$date_object1=new DateTime($datetime_string_from_mysql, new DateTimeZone('UTC');
$date_object1->setTimezone($user_timezone);
$string_for_display_in_application = $date_object1->format('m/d/Y g:i a'); |
使用此方法,您的日期时间值总是存储在数据库中的UTC中,并且用户总是体验到他/她的配置文件时区中的值。如果每个时区有必要,PHP将更正夏令时。
一言为定:这个解释不包括mysql时间戳数据类型。我建议使用mysql datetime datetime来存储datetime值,而不是timestamp数据类型。时间戳数据类型在这里的手册中介绍。
编辑:可以使用listIdentifiers生成一个数组,其中包含每个php时区字符串,这是datetimezone类的静态方法。
- 这会自动更改日期吗?假设8月10日上午1:00为英国开了一个会议,如果我邀请来自美国的人,它会自动在正确的时区和8月9日休假后显示会议吗?
- 是的,在这种情况下,日期将从8月10日更改为8月9日。我建议做些测试。在英国创建一个php datetime,var_转储该值,更改对象的时区,然后var_再次转储。日期时间既是日期又是时间,它们是PHP对象不可分割的属性。
- 令人惊叹的!日期和时间可以单独保存,还是必须在一列中保存到数据库中?
- 我建议在mysql date time数据类型中保存任何既有日期又有时间的值。当只需要这些部分时,MySQL还具有日期数据类型和时间数据类型。手册在这里解释。我能投赞成票吗?
- 我刚刚尝试了这些,当插入数据库时,它可以正常工作。但是当我用您的第二个查询从数据库中读取时,它似乎不起作用。这是我试过的代码:$startdatetimeobject=new DateTime($row['StartDateAndTime'], new DateTimeZone('UTC'); $startdatetimeobject->setTimezone($user_timezone); $start = $startdatetimeobject->format('m/d/Y g:i a'); 。
- 你需要比"它不起作用"更具体一些。你期望发生什么,而不是发生什么?
- 我希望它通过回显$start变量来回显开始日期和时间。相反,它只是打断页面(此代码在页面中的包含文件中,包含文件之外的页面的其余部分工作,但不工作)。希望有帮助。
- 处理时区的方法有效,这可能不是讨论调试代码的地方。
- 我在做了一些调整后终于找到了它,不过还是谢谢你的回答。
- 我已经在服务器端使用了您的技术php/mysql,然后使用这个JS库来检测用户的时区pellepim.bitback.org/jtz它并不完美,但是我可以自动检测用户的时区,然后将其保存到会话中并刷新页面以正确显示日期。这样我就不用问用户了,如果他搬到另一个国家,在他的电脑里改变了,他也不需要改变它。
在MySQL中,您需要做的是:
将每个用户选择的时区存储到您可以在代表该用户进行数据库查询时检索到的位置。您可以将其存储为字符串。
在代表特定用户工作(例如,存储或检索预约时间和日期)之前,先执行SET time_zone = (stored time zone setting)。
这将导致时区适当地转换为每个人的本地时间。
编辑:
这是因为
MySQL尝试使用UTC(通用时间,以前称为格林威治标准时间)在表中存储日期时间和时间戳数据项。
只有当它知道应用程序给定的每个数据项的正确本地时区时,它才能正确地执行此操作。
在不关心不同时区的应用程序中,它以一种mysql服务器范围的方式来实现这一点。请参阅https://dev.mysql.com/doc/refman/5.5/en/time-zone-support.html。大多数运行多国家和多时区应用程序的人将其服务器时区设置为UTC,而不是本地时间,因为这样可以更容易地将问题解决。
除非您还知道日期和时区,否则尝试将时间从UTC转换为本地时间是没有意义的,因为本地时间在一年中的不同时间打开和关闭。试着让以色列、亚利桑那和纽约的三个国家都明白这一点,我敢说!以色列在逾越节和Rosh Hashanah的白天和标准时间之间切换;亚利桑那州不切换,纽约根据美国联邦立法机构的意愿切换。
有一个会话范围的时区设置(SET time_zone = something)。如果不进行设置,则使用上面第3项中的时区表示。如果设置了它,服务器将使用它作为时区,将其内部表示转换为它在查询中发送回的表示。
您可以通过发出SELECT Name from mysql.time_zone_name来获取mysql服务器中可用时区的名称列表。这可以填充下拉菜单,用户可以从中选择时区。如果此查询未返回任何项,请查看https://dev.mysql.com/doc/refman/5.5/en/time-zone-support.html的底部。
所以,这意味着您可以将会话时区设置设置为特定用户的时区,然后在该用户的时区中返回所有时间。此外,您的INSERT或UPDATE中的任何DATETIME或TIMESTAMP项都将从该用户的时区转换为mysql的内部表示,因为它们放在您的表中。
注意:在具有持久性MySQL连接的Web应用程序中,新用户请求的工作将继承连接的时区设置。别忘了为新用户重置它。
如果您正在运行一个为多个用户返回本地时间数据的查询,而这些用户恰好位于不同的时区,则不能利用此MySQL每会话功能集。您可以通过为不同的用户运行不同的查询并更改他们之间的时区设置来解决这个问题。
或者,您可以使用mysql函数
1
| CONVERT_TZ(datetime,'UTC','user_time_zone') |
或在每件物品上相似。
另外,Java和dotnet有自己的高质量时区操作系统。因此,您可以选择使用UTC时区设置运行MySQL服务器,并在应用程序中进行所有时区转换。
- 我认为任何时候显示在站点上的时间都是显示在用户时区的时间吗?不需要任何魔法?
- 如果您执行的查询从两个具有不同时区的用户那里获取时间,您会怎么做?
- 看看我的编辑…
- 我更喜欢根据用户配置文件时区参数在PHP中处理时区。PHP的粒度要大得多,因为每个datetime对象都可以有自己的时区。通过设置和重置环境连接变量,MySQL强制您对每个MySQL值使用相同的时区。此外,MySQL计算在大多数大型Web应用程序中都很昂贵和稀缺,但PHP处理却非常丰富和便宜。我提出了另一种方法来回答这个问题。