【问题标题】:How to deal with dates in global system如何处理全局系统中的日期
【发布时间】:2020-09-18 18:12:49
【问题描述】:

假设我需要创建“类似聊天”的系统。当然,我需要以某种方式处理日期。 我读了很多关于它的知识,但我真的不知道如何使用它。

  1. 我想以 UTC 格式存储消息日期(postgres 12)

  2. 每个用户都应该能够选择他的时区,并且这个时区应该保存到数据库中(标准方法)

  3. 从数据库中检索消息时,我需要根据用户选择的时区将消息日期转换为有效的本地日期。

这真的是我需要做的,问题从这里开始:

  1. 在 postgres 中,日期以偏移量 f.e 2020-05-01 00:00:00+02 存储,但我想将时区存储在另一个表中,而不是此处

  2. 如何存储用户时区?我应该使用“EST5EDT”之类的名称还是使用时间偏移量作为整数?

  3. 在哪里可以找到所有时区的列表来呈现用户? (每个全球网站 f.e. facebook 都有带有偏移的时区列表,我在哪里可以找到所有有效时区的列表?)

  4. 如何选择具有用户适当时区的日期? f.e.

    SELECT convert_to_user_date("Date", "timezonename??")
    FROM "Messages"
    

这是实现我的目标的正确方法吗?

【问题讨论】:

    标签: postgresql datetime timezone


    【解决方案1】:

    如今,您不必求助于 UTC。您可以使用时区存储完整的时间戳。这种方式例如在时间戳记录在数据库中时,您不会丢失 DST 状态。 https://www.postgresql.org/docs/current/datatype-datetime.html

    您可以轻松选择存储的时间戳,并将任何时区转移到目标用户的时区(假设它存储在用户首选项中的某个位置)。语法为SELECT ... AT TIME ZONE https://www.postgresql.org/docs/current/functions-datetime.html#FUNCTIONS-DATETIME-ZONECONVERT

    【讨论】:

      【解决方案2】:

      您已经非常接近可行的设置了。

      首先,使用timestamptimestamp without timezone 列数据类型来存储这些UTC 日期/时间戳。

      其次,以Asia/KolkataAmerica/Halifax 的形式将用户的首选时区存储在varchar(63) 列中。

      第三,使用 postgresql 的内置视图pg_timezone_names 获取有效时区列表。您可以使用它来填充用户设置屏幕中的下拉选项列表。

      如果您有时间在用户设置屏幕上进行一些真正出色的操作,您可以建议您根据用户的 IP 地址猜测的时区设置,并允许他们在您的猜测错误时更改它们。读这个。 How to get Time Zone through IP Address in PHP

      然后,当您的应用程序开始代表任何用户使用 postgresql 时,在您的用户表中查找该用户选择的时区,并在此 SQL 命令中使用它。 SET TIME ZONE 'America/Halifax';(无论用户选择什么)。

      然后,当您检索时间戳时,它们将以用户的本地时间呈现,而当您存储它们时,它们将采用 UTC。

      'toobz 对此充满了建议。这里有一些可能有用的东西。 How to get Time Zone through IP Address in PHP

      【讨论】:

      • 我有一个关于完整性的问题。我需要插入已由客户端转换为 utc 的日期还是使用用户日期?我问是因为根据这个线程:stackoverflow.com/questions/44432682/… 我应该将日期时间存储在timestamp WITH time zone 中(你建议使用timestamp WITHOUT time zone)。我的情况有什么不同?
      【解决方案3】:

      使用数据类型timestamp with time zone。不用担心名称 - 该数据类型确实代表一个绝对时间点,并且不存储时区信息。

      您唯一需要做的就是为客户端连接的时区正确设置timezone参数,然后该值将在该时区正确表示。 PostgreSQL 为您完成所有工作。

      如果您不喜欢字符串表示形式(例如,您对显示的时区偏移感到不安),请使用to_char 以您喜欢的方式格式化输出:

      CREATE TABLE dates (x timestamp with time zone NOT NULL);
      
      SET timezone = 'Europe/Vienna';
      
      INSERT INTO dates VALUES ('2020-06-01 03:00:00');
      
      SET timezone = 'Asia/Kolkata';
      
      SELECT to_char(x, 'YYYY-MM-DD HH24:MI:SS') FROM dates;
      
             to_char       
      ---------------------
       2020-06-01 06:30:00
      (1 row)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-01-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多