Лучший способ сериализации часов в значимые данные - PullRequest
2 голосов
/ 22 декабря 2009

Часть моего веб-приложения включает создание «встреч» (смен) с использованием селектора с перетаскиванием для каждого дня. В настоящее время эти данные сериализируются примерно так:

9,10,11,12,13,14,15,16,76,77,78,298,299,300,301,302,303,304,

Где каждое число представляет n-ную получасовую неделю (таким образом, 304 - это 300-я получасовая половина недели или 8 утра в субботу).

Затем я анализирую это на сервере с Python во что-то более разумное:

[[9,16],[76,78],[298,304]]

Но тогда у меня возникают проблемы с аккуратным преобразованием их в datetime объектов, в основном из-за того, как ... липкие данные отправляются на сервер, в первую очередь.

У меня такой вопрос: Каков «лучший» способ сериализации выбранных «сдвигов» и преобразования их в datetime объекты с использованием Javascript и Python

У меня есть живая версия дрянного HTML / Javascript, который я придумал. Я использую Javascript / jQuery на стороне клиента и Python / Django на сервере.

Ответы [ 2 ]

2 голосов
/ 22 декабря 2009

Вы говорите об интервалах.

Лучший способ иметь интервал - это время начала и продолжительность.

class Shift( object ):
    def __init__( self, start, length ):
         self.start= start
         self.length= length
    def __repr__( self ):
         return "Shift(%d,%d)" % ( self.start, self.length )
    def ends( self ):
         return self.start + self.length

Вы можете сериализовать эти объекты.

[ Shift(9,6), Shift(76,2), Shift(298,6) ]

Вы можете реализовать операторы для сравнения смен, чтобы увидеть, перекрываются ли они или один содержит другой.

Почему длина? Почему бы не закончить время?

Оказывается, что некоторые математические приемы обнаружения перекрытий и сдерживания кажутся немного более простыми, если вы считаете, что интервалы начинаются в определенное время и выполняются в течение заданного времени. Я обнаружил, что немного легче доказать, что между сдвигами, сделанными таким образом, нет пробелов.

Вы хотите использовать "полуоткрытый" интервал. Время начала включено в смену, но время окончания не включено.

def contains( self, aTime ):
    return self.start <= aTime < self.start + self.length

def before( self, nextShift ):
    return self.start + self.length == nextShift.start

def after( self, prevShift ):
    return prevShift.ends() == self.start

Чтобы преобразовать в дату и время, вам нужна базовая дата для начала недели. Затем вы можете сделать некоторые математические расчеты, чтобы определить время начала смены. Длина - это (тривиально) интервал.

def startDatetime( self, week_start_datetime ):
    offset= datetime.timedelta( seconds= self.start*30*60 )
    return week_start_datetime + offset

def lengthTimedelta( self ):
    return datetime.timedelta( seconds= self.length*30*60 )

def endDatetime( self, week_start_datetime ):
    return self.startDatetime( week_start_datetime ) + self.lengthTimedelta()
1 голос
/ 22 декабря 2009

Итак, если у вас есть код для извлечения диапазонов (т.е. 1,2,3,4 преобразуется в [1,4]), я не понимаю, почему вы не можете использовать стандартную арифметику даты / времени.

from datetime import datetime, timedelta

def get_shift(start_of_week, start, end):
    """Returns a 2-tuple of datetimes"""
    HALF_HOUR = timedelta(minutes=30)
    return start_of_week + start * HALF_HOUR, start_of_week + (end + 1) * HALF_HOUR

start_of_week должно быть понедельником 00:00. Чтобы использовать это, вам нужен способ расчета «понедельник 00:00» для любой данной недели.

Эта функция возвращает понедельник 00:00 для недели, содержащей переданную ей дату. Попробуйте например start_of_week_containing(datetime.now()).

def start_of_week_containing(dt):
    while dt.weekday() > 0:
        dt = dt - timedelta(days=1)
    return datetime(dt.year, dt.month, dt.day, 0, 0, 0)

Полный пример:

start_of_week = start_of_week_containing(datetime.now())
shift_start, shift_end = get_shift(start_of_week, 4, 9)
# now shift_start and shift_end will contain datetime objects
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...