2012-04-24 24 views
10

Tôi đã đấu tranh quá lâu vào ngày/giờ trong Python và nghĩ rằng ai đó có thể đưa cho tôi một bàn tay ở đây.Python chuyển tzinfo thành ngày giờ ngây thơ mà không cần pytz

Về cơ bản tôi muốn thực hiện chuyển đổi bằng UTC và tính đến các thay đổi DST.

tôi đã tạo ra những điều sau tzinfo lớp từ một trong những hướng dẫn Python (không chính xác 100% Tôi biết nhưng nó không cần):

from datetime import tzinfo, timedelta, datetime 

ZERO = timedelta(0) 
HOUR = timedelta(hours=1) 

def first_sunday_on_or_after(dt): 
    days_to_go = 6 - dt.weekday() 
    if days_to_go: 
     dt += timedelta(days_to_go) 
    return dt 

DSTSTART_2007 = datetime(1, 3, 8, 2) 
DSTEND_2007 = datetime(1, 11, 1, 1) 
DSTSTART_1987_2006 = datetime(1, 4, 1, 2) 
DSTEND_1987_2006 = datetime(1, 10, 25, 1) 
DSTSTART_1967_1986 = datetime(1, 4, 24, 2) 
DSTEND_1967_1986 = DSTEND_1987_2006 

class USTimeZone(tzinfo): 

    def __init__(self, hours, reprname, stdname, dstname): 
     self.stdoffset = timedelta(hours=hours) 
     self.reprname = reprname 
     self.stdname = stdname 
     self.dstname = dstname 

    def __repr__(self): 
     return self.reprname 

    def tzname(self, dt): 
     if self.dst(dt): 
      return self.dstname 
     else: 
      return self.stdname 

    def utcoffset(self, dt): 
     return self.stdoffset + self.dst(dt) 

    def dst(self, dt): 
     if dt is None or dt.tzinfo is None: 
      # An exception may be sensible here, in one or both cases. 
      # It depends on how you want to treat them. The default 
      # fromutc() implementation (called by the default astimezone() 
      # implementation) passes a datetime with dt.tzinfo is self. 
      return ZERO 
     assert dt.tzinfo is self 

     # Find start and end times for US DST. For years before 1967, return 
     # ZERO for no DST. 
     if 2006 < dt.year: 
      dststart, dstend = DSTSTART_2007, DSTEND_2007 
     elif 1986 < dt.year < 2007: 
      dststart, dstend = DSTSTART_1987_2006, DSTEND_1987_2006 
     elif 1966 < dt.year < 1987: 
      dststart, dstend = DSTSTART_1967_1986, DSTEND_1967_1986 
     else: 
      return ZERO 

     start = first_sunday_on_or_after(dststart.replace(year=dt.year)) 
     end = first_sunday_on_or_after(dstend.replace(year=dt.year)) 

     # Can't compare naive to aware objects, so strip the timezone from 
     # dt first. 
     if start <= dt.replace(tzinfo=None) < end: 
      return HOUR 
     else: 
      return ZERO 

Ở phía bên kia Tôi có một tùy date đối tượng trong EST và tôi muốn biết số giờ họ khác nhau bằng cách tính đến DST.

Tôi đã thử một cái gì đó như thế này:

>>> Eastern = ustimezone.USTimeZone(-5, "Eastern", "EST", "EDT") 
>>> x = datetime.date.today() # I actually get an arbitrary date but this is for the example 
>>> x_dt = datetime.datetime.combine(x, datetime.time()) 
>>> x_dt_tz = x_dt.astimezone(Eastern) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
ValueError: astimezone() cannot be applied to a naive datetime 

Tôi đã nhìn thấy nhiều bài viết nói người sử dụng localize từ các module pytz, nhưng tiếc là tôi không thể sử dụng các module bổ sung, vì vậy không thể sử dụng pyzt

Có ai biết làm thế nào tôi có thể nhận được datetime ngây thơ này vào một đối tượng thời gian mà không sử dụng pytz?

+1

x_dt.replace (tzinfo = Đông) có lẽ? Từ đọc: http://groups.google.com/group/google-appengine/browse_thread/thread/17add9b3070aad7e/b995fe7e1f16cd4e –

+1

@skyl perfect, x_dt.replace (tzinfo = Eastern) .utcoffset() trả về datetime.timedelta (-1 , 72000) tương ứng với -4 giờ! Điều đó dường như rất phức tạp cho một điều đơn giản như vậy nhưng nhờ sự giúp đỡ, bạn nên đăng nó như là một câu trả lời và tôi sẽ chấp nhận nó. –

+0

xử lý DST mà không có 'pytz' giống như xử lý nhiều ngôn ngữ mà không cần Unicode. Nó có thể được thực hiện nhưng kết quả sẽ là sai trong số trường hợp. – jfs

Trả lời

7

Sử dụng x_dt.replace(tzinfo=Eastern) (found from this Google Groups thread).

x_dt.replace(tzinfo=Eastern).utcoffset() trả về datetime.timedelta(-1, 72000) tương ứng với -4 giờ! (từ nhận xét của Câu hỏi)

11

Đối với giá trị của nó, câu trả lời @skyl được cung cấp tương đương hoặc ít hơn với những gì pytz thực hiện.

Đây là nguồn có liên quan pytz. Nó chỉ gọi replace trên đối tượng datetime với tzinfo kwarg:

def localize(self, dt, is_dst=False): 
    '''Convert naive time to local time''' 
    if dt.tzinfo is not None: 
     raise ValueError('Not naive datetime (tzinfo is already set)') 
    return dt.replace(tzinfo=self) 
+2

+1 để tìm nguồn –

+0

@CharlesMenguy: không, nó không phải là những gì 'pytz' làm cho timezones với DST (*" Tôi muốn làm một chuyển đổi trong UTC và có tính đến các thay đổi DST tài khoản. "*). Bạn chỉ có thể sử dụng '.replace()' với các múi giờ bù đắp cố định như UTC (cùng độ lệch UTC từ thời điểm bắt đầu đến cuối cùng). – jfs

Các vấn đề liên quan