2014-12-17 24 views
7

Đây chỉ là một bài đăng khác trên pytz.Chuyển đổi múi giờ theo thời gian bằng pytz

Có hai chức năng để chuyển đổi đối tượng ngày giờ giữa hai múi giờ. Các hàm thứ hai hoạt động cho tất cả các trường hợp. Hàm đầu tiên thất bại trong hai trường hợp, (3) và (4). Tương tự SO post không có vấn đề như thế này. Bất kỳ giải thích nào dựa trên sự khác biệt giữa localize(datetime.datetime)replace(tzinfo) sẽ là một trợ giúp tuyệt vời.

>>> from dateutil.parser import parse 
>>> import pytz 

chức năng đầu tiên (buggy)

Hàm dưới đây sử dụng datetime.datetime.replace(tzinfo).

def buggy_timezone_converter(input_dt, current_tz='UTC', target_tz='US/Eastern'): 
    '''input_dt is a datetime.datetime object''' 
    current_tz = pytz.timezone(current_tz) 
    target_tz = pytz.timezone(target_tz) 
    target_dt = input_dt.replace(tzinfo=current_tz).astimezone(target_tz) 
    return target_tz.normalize(target_dt) 

Lưu ý bốn chuyển đổi giờ hiện tại.

(1) từ UTC để EST - OK

>>> buggy_timezone_converter(parse('2013-02-26T04:00:00')) 
Out[608]: datetime.datetime(2013, 2, 25, 23, 0, tzinfo=<DstTzInfo 'US/Eastern' EST-1 day, 19:00:00 STD>) 

(2) từ UTC để EDT - OK

>>> buggy_timezone_converter(parse('2013-05-26T04:00:00')) 
Out[609]: datetime.datetime(2013, 5, 26, 0, 0, tzinfo=<DstTzInfo 'US/Eastern' EDT-1 day, 20:00:00 DST>) 

(3) từ EST để tính theo giờ UTC - Không OK. Thời gian bù đắp là 4 giờ 56 phút. Nó được cho là 5 giờ

>>> buggy_timezone_converter(parse('2013-02-26T04:00:00'), target_tz='UTC', current_tz='US/Eastern') 
Out[610]: datetime.datetime(2013, 2, 26, 8, 56, tzinfo=<UTC>) 

(4) từ EDT đến UTC - Không OK. Thời gian bù đắp là 4 giờ 56 phút. Nó được cho là 4 giờ. Tiết kiệm ánh sáng ban ngày không được xem xét.

>>> buggy_timezone_converter(parse('2013-05-26T04:00:00'), current_tz='US/Eastern', target_tz='UTC') 
Out[611]: datetime.datetime(2013, 5, 26, 8, 56, tzinfo=<UTC>) 

chức năng thứ hai (Tác phẩm hoàn hảo)

Hàm dưới đây sử dụng pytz.timezone.localize(datetime.datetime). Nó hoạt động một cách hoàn hảo

def good_timezone_converter(input_dt, current_tz='UTC', target_tz='US/Eastern'): 
    current_tz = pytz.timezone(current_tz) 
    target_tz = pytz.timezone(target_tz) 
    target_dt = current_tz.localize(input_dt).astimezone(target_tz) 
    return target_tz.normalize(target_dt) 

(1) từ UTC để EST - OK

>>> good_timezone_converter(parse('2013-02-26T04:00:00')) 
Out[618]: datetime.datetime(2013, 2, 25, 23, 0, tzinfo=<DstTzInfo 'US/Eastern' EST-1 day, 19:00:00 STD>) 

(2) từ UTC để EDT - OK

>>> good_timezone_converter(parse('2013-05-26T04:00:00')) 
Out[619]: datetime.datetime(2013, 5, 26, 0, 0, tzinfo=<DstTzInfo 'US/Eastern' EDT-1 day, 20:00:00 DST>) 

(3) từ EST để UTC - OK.

>>> good_timezone_converter(parse('2013-02-26T04:00:00'), current_tz='US/Eastern', target_tz='UTC') 
Out[621]: datetime.datetime(2013, 2, 26, 9, 0, tzinfo=<UTC>) 

(4) từ EDT đến UTC - OK.

>>> good_timezone_converter(parse('2013-05-26T04:00:00'), current_tz='US/Eastern', target_tz='UTC') 
Out[620]: datetime.datetime(2013, 5, 26, 8, 0, tzinfo=<UTC>) 
+0

Không thể sao chép: '>>> timezone_converter (datetime.datetime (2013,02,26,4,0,0,0), target_tz = 'UTC', current_tz = 'US/Eastern')' ' datetime.datetime (2013, 2, 26, 9, 0, tzinfo = ) ' –

+0

Xin lỗi, quên thêm các dòng nhập >>> từ phân tích nhập dateutil.parser >>> nhập pytz –

+0

Hoặc câu hỏi của bạn là bản sao của [pytz localize vs datetime replace] (http://stackoverflow.com/q/1379740/4279) hoặc bạn nên hỏi một câu hỏi cụ thể hơn ([cập nhật câu hỏi hiện tại] (http://stackoverflow.com/posts/ 27531718/chỉnh sửa)) nếu bạn không hài lòng với câu trả lời hiện có. Vui lòng sử dụng các tên khác nhau cho hàm đầu tiên và hàm thứ hai, ví dụ: 'convert_tz_replace()' và 'convert_tz()'. – jfs

Trả lời

10

Tôi giả sử bạn có những câu hỏi này:

  • tại sao công việc chức năng đầu tiên cho múi giờ UTC?
  • tại sao không thành công cho múi giờ 'US/Eastern' (ví dụ: DstTzInfo)?
  • tại sao chức năng thứ hai hoạt động cho tất cả các ví dụ được cung cấp?

Chức năng đầu tiên không chính xác vì nó sử dụng d.replace(tzinfo=dsttzinfo_instance) thay vì dsttzinfo_instance.localize(d).

Chức năng thứ hai là chính xác hầu hết thời gian, ngoại trừ trong thời gian mơ hồ hoặc không tồn tại ví dụ, trong quá trình chuyển đổi DST - bạn có thể thay đổi hành vi bằng cách truyền tham số để is_dst.localize(): False (mặc định)/True/None (nâng cao một ngoại lệ).

Hàm đầu tiên hoạt động trong múi giờ UTC vì hàm này có giá trị chênh lệch utc cố định (0) cho bất kỳ ngày nào. Các múi giờ khác như America/New_York có thể có các chênh lệch utc khác nhau vào các thời điểm khác nhau (Giờ tiết kiệm ánh sáng, thời gian chiến tranh, bất kỳ thời điểm nào mà một số chính trị gia địa phương có thể nghĩ là ý tưởng hay - có thể là mọi thứ - cơ sở dữ liệu tz hoạt động trong hầu hết các trường hợp). Để triển khai các phương thức tzinfo.utcoffset(dt), tzinfo.tzname(dt), tzinfo.dst(dt)pytz sử dụng bộ sưu tập DstTzInfo mỗi trường hợp có một bộ thuộc tính khác nhau là (_tzname, _utcoffset, _dst). Cho dt (ngày/giờ) is_dst, .localize(), chọn một cách thích hợp (trong hầu hết các trường hợp nhưng không phải lúc nào cũng là) DstTzInfo ví dụ từ bộ sưu tập. pytz.timezone('America/New_York') trả về một trường hợp DstTzInfo với (_tzname, _utcoffset, _dst) thuộc tính tương ứng với một số không có giấy tờ khoảnh khắc trong thời gian (khác pytz phiên bản có thể trả về giá trị khác nhau - phiên bản hiện tại có thể trở lại tzinfo dụ tương ứng với ngày sớm nhất mà zoneinfo có sẵn - bạn don 't muốn giá trị này hầu hết thời gian: tôi nghĩ rằng động lực đằng sau sự lựa chọn của giá trị mặc định là để làm nổi bật các lỗi (qua pytz.timezone-datetime constructor hoặc .replace() phương pháp)

để tóm tắt:. .localize() chọn thích hợp UTCOFFSET, tzname , giá trị dst, .replace() sử dụng giá trị mặc định (không phù hợp). UTC đã bật ly một bộ utcoffset, tzname, dst do đó giá trị mặc định có thể được sử dụng và phương thức .replace() hoạt động với múi giờ UTC. Bạn cần truyền một đối tượng datetime và tham số is_dst để chọn các giá trị thích hợp cho các múi giờ khác như 'America/New_York'.

Về nguyên tắc, pytz có thể gọi localize() phương pháp để thực hiện utcoffset(), tzname(), dst() phương pháp ngay cả khi dt.tzinfo == self: nó sẽ làm cho những phương pháp O (log n) trong thời gian nơi n là số khoảng cách với nhau (UTCOFFSET, tzname, dst) giá trị nhưng datetime hàm tạo và .replace() sẽ hoạt động như nghĩa là, lệnh gọi localize() rõ ràng sẽ chỉ cần thiết để vượt qua is_dst.

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