关于python:如何处理客户端和服务器之间的日期差异?

How to handle date difference between client and server?

我有一台API,看起来像

1
/summary/yyyy/mm
  • 它返回请求的年份和月份的数据摘要。
  • 它返回当前年份和月份的剩余天数。例如:days_left: 9用于201310,服务器上的当前日期为21 Oct 2013

如何计算剩余天数?这在python中实现为

1
2
3
4
5
6
7
8
9
10
11
12
def current_financial_month_details(self):
        time_from, time_to = self \
            .get_start_end_time_current_financial_month()

        today = datetime.today()
        from_time = datetime(year=today.year, month=today.month,
                             day=today.day)
        return {
            'time_from': time_from,
            'time_to': time_to,
            'remaining_days': (time_to - from_time).days
        }

问题是什么?

  • 服务器位于东海岸,客户机(带浏览器的ME)位于太平洋时区。
  • 当太平洋标准时间下午9点,东海岸的时间发生了变化,所以如果我在太平洋标准时间跑步时撞上了/summary/2013/10,如果我在太平洋标准时间跑步时是Oct 21 2013,那么日期已经在东部标准时间发生了变化,所以days_left: 8在客户端是不正确的。正确的?

我该如何处理这种情况?


大多数人认为最好的做法是将日期和时间存储在一个时区内,而不受地理位置的影响——通常是UTC。如果您有一个服务将从具有不同时区的位置访问(或最终可能被访问),则同样适用。

正如j0hn提到的,当客户机与服务器交互时,他们应该负责从/到UTC的转换。在您的情况下,这意味着days_left应定义为当前UTC日期和月末(以UTC为单位)之间的天数。

尤其是对于Python,有两种类型的datetime.datetime对象:naive和timezone-aware。naive datetime不附加任何时区信息,因此一个好的做法(在网络程序中)是在UTC时区中只对时间使用naive datetime。要进行计算(例如减去两个日期),请考虑使用datetime.utcnow而不是datetime.now,这样可以避免任何与时区相关的问题,包括(但不限于)DST导致的错误时间增量。

如果您确实需要处理其他时区(例如显示给用户),您可能需要使用外部库,因为Python本身不提供时区数据库。这个问题有更多的信息。


你有几个选择。

首先是指定交付结果的时区,并期望客户能够接受差异。明显的选择是服务器时区或UTC。

第二种方法是让API返回当前日期和天数。它不会改变结果,但至少你能发现日期与你期望的日期不同。

第三,让API接受时区输入,以便服务器可以调整其处理。

第四是在午夜以外的某个时间更改日期,例如上午5点。只有当你的客户都在类似的时区,而且你的活动不是全天候的,这才有效;如果你在中国有客户,你可能会后悔这个选择。