2013-11-05 13 views
6

Có những lúc bạn cần thu thập thời gian từ người dùng mà không cần thu thập ngày được liên kết. Ví dụ: nếu người dùng định cấu hình sự kiện lặp lại chạy hàng ngày cùng một lúc. Django của TimeField không chơi với múi giờ mặc dù. Tuy nhiên, trong trường hợp cụ thể này (và có lẽ bất cứ khi nào bạn ghi lại thời gian một mình), múi giờ là một yếu tố quan trọng. Vì vậy, làm thế nào để bạn lưu trữ một thời gian nhận thức múi giờ?Làm thế nào để làm cho TimeField nhận biết múi giờ?

Trả lời

4

Câu trả lời là bạn không. Trong một thời gian để nhận biết múi giờ, nó phải có một ngày liên kết với nó. Hãy suy nghĩ về tiết kiệm ánh sáng ban ngày ... Giải pháp của tôi cho điều này là sử dụng một DateTimeField trên mô hình và ghi đè lên các hình thức như sau:

# Model 
class MyModel(models.Model): 
    time_of_day = models.DateTimeField() 

# Form Fields 
from django.forms.util import from_current_timezone 
from django.forms.util import to_current_timezone 
from django.utils import timezone 

class TzAwareTimeField(forms.fields.TimeField): 
    def prepare_value(self, value): 
     if isinstance(value, datetime.datetime): 
      value = to_current_timezone(value).time() 
     return super(TzAwareTimeField, self).prepare_value(value) 

    def clean(self, value): 
     value = super(TzAwareTimeField, self).to_python(value) 
     dt = to_current_timezone(timezone.now()) 
     return dt.replace(
      hour=value.hour, minute=value.minute, 
      second=value.second, microsecond=value.microsecond) 


# Forms 
class MyForm(forms.ModelForm): 
    time_of_day = TzAwareTimeField() 
+3

Tuyên bố mở của bạn (và hành vi của Django) không nhất quán với cách Python xử lý các đối tượng 'thời gian'. Một đối tượng 'time' của Python có thể có trường' tzinfo', cho phép đối tượng 'time' nhận biết múi giờ không có ngày liên quan, mà _is_ có ích trong một số trường hợp, như khi ngày được lưu ở nơi khác. Tôi chỉ gặp vấn đề này với 'open_time' và' close_time' 'TimeField's trên mô hình' Day' ở Django. Những thời điểm đó lý tưởng là nhận thức về múi giờ, nhưng không thể vì Django không ủng hộ điều đó. – jbg

+0

Đây là cũ, nhưng vẫn hữu ích, vì vậy tôi muốn chỉ ra rằng tôi nghĩ rằng bạn cần phải quấn giá trị trả về của phương thức 'clean' trong' from_current_timezone'. –

0

Đây là chưa được kiểm tra và không đầy đủ:

class TimeFieldWithZone(TimeField): 
    def db_type(self, connection): 
     if (connection.settings_dict['ENGINE'] == 
      'django.db.backends.postgresql_psycopg2'): 
      return 'time with time zone' 
     raise Exception('Unsupported database type') 

    def get_db_prep_value(self, value, *args, **kwargs): 
     try: 
      return super(TimeFieldWithZone, self).get_db_prep_value(
       value, *args, **kwargs) 
     except ValueError: 
      return six.text_type(value) 

này sẽ sử dụng Postgaty 'time with time zone kiểu dữ liệu. Nó sẽ phá vỡ nếu bạn vượt qua nó một chuỗi trong định dạng 'HH: MM: SS.mmmmmm + HH: MM' và sử dụng auto_now sẽ cố gắng để tiết kiệm một thời gian ngây thơ (không chắc chắn nếu đó ném một lỗi).

chỉnh sửa

Trong mã phụ trợ chung, ngoại lệ được ném nếu bạn thử chèn thời gian với múi giờ khác với UTC.

chỉnh sửa 2

tôi đã thêm một cập nhật get_db_prep_value để chuyển đổi một quy time với múi giờ vào một chuỗi, nhưng nó chỉ hoạt động nếu múi giờ cung cấp kết quả đầu ra một utc bù đắp (có thể mơ hồ mà không có một ngày).

Có vẻ như time with time zone là một chút gây hiểu lầm ... Theo như tôi có thể nói, nó thực sự lưu trữ thời gian có chênh lệch UTC và KHÔNG phải là múi giờ. Vì vậy sẽ rất khó để lấy giá trị trả lại, thêm ngày lịch và lấy lại thời gian thích hợp liên quan đến thời gian tiết kiệm ánh sáng ban ngày.

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