我的网络应用程序的一部分涉及使用每天的拖放选择器创建“约会”(轮班)。目前,此数据已序列化为以下内容:
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
个对象,这主要是因为......首先将数据发送到服务器的方式很糟糕。
我的问题是:序列化所选“轮班”并使用Javascript和Python将其转换为datetime
个对象的“最佳”方式是什么
我提出了live version粗略的HTML / Javascript。我在客户端使用Javascript / jQuery,在服务器上使用Python / Django。
答案 0 :(得分:2)
你在谈论间隔。
获得间隔的最佳方式是开始时间和持续时间。
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
要转换为datetime,您需要一周开始的基准日期。然后,您可以进行一些数学计算以确定班次开始时间。长度(平凡)是一个间隔。
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 :(得分:1)
好吧,假设你有代码来提取范围(即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