def check_start_end_duration \ (date, start, end, duration, new_values, dist = 0) : """ either duration or both start/end must be set but not both of duration/end set duration from start/end if duration empty set end from start/duration if end empty Note: We are using naive times (with timezone 0) here, this means we can safely use date.pretty for converting back to string. """ dstart = dend = None if dist : check_duration (dist) if start and ":" not in start : start = start + ":00" if end and ":" not in end : end = end + ":00" if 'end' in new_values : if not start : attr = _ ('start') raise Reject, _ (''"%(attr)s must be specified") % locals () if 'duration' in new_values : raise Reject, _ (''"Either specify duration or start/end") dstart, dend, sp, ep, dur = check_timestamps (start, end, date) duration = dur new_values ['duration'] = duration new_values ['start'] = sp new_values ['end'] = ep else : check_duration (duration, 24) if 'duration' in new_values : new_values ['duration'] = duration if start : if 'start' in new_values or 'duration' in new_values : minutes = duration * 60 hours = int (duration % 60) minutes = minutes - hours * 60 ds = Date (start, offset = 0) t = (ds + Interval ('%d:%d' % (hours, minutes))).pretty \ (hour_format) if duration > 0 and t == '00:00' : t = '24:00' dstart, dend, sp, ep, dur = check_timestamps (start, t, date) assert dur == duration new_values ['start'] = sp new_values ['end'] = ep if dist and dist < duration : duration -= dist if start : hours = int (dist) minutes = (dist - hours) * 60 if not dstart : dstart = Date (start, offset = 0) dstart = dstart + Interval ('%d:%d' % (hours, minutes)) new_values ['start'] = dstart.pretty (hour_format) new_values ['duration'] = duration return dstart, dend
def testGranularity(self): ae = self.assertEqual ae(str(Date('2003-2-12', add_granularity=1)), '2003-02-12.23:59:59') ae(str(Date('2003-1-1.23:00', add_granularity=1)), '2003-01-01.23:00:59') ae(str(Date('2003', add_granularity=1)), '2003-12-31.23:59:59') ae(str(Date('2003-5', add_granularity=1)), '2003-05-31.23:59:59') ae(str(Date('2003-12', add_granularity=1)), '2003-12-31.23:59:59') ae(str(Interval('+1w', add_granularity=1)), '+ 14d') ae(str(Interval('-2m 3w', add_granularity=1)), '- 2m 14d')
def testCollision(self): # fake up an actual change self.action.classname = 'test' self.action.nodeid = '1' self.client.parsePropsFromForm = lambda: ({('test', '1'): {1: 1}}, []) self.failUnless( self.action.detectCollision(self.now, self.now + Interval("1d"))) self.failIf( self.action.detectCollision(self.now, self.now - Interval("1d"))) self.failIf(self.action.detectCollision(None, self.now))
def testIntervalSubtractYearBoundary(self): # force the transition over a year boundary now = Date('2003-01-01.00:00:00') then = now - Interval('2d') self.assertEqual(str(then), '2002-12-30.00:00:00') now = Date('2004-02-01.00:00:00') then = now - Interval('365d') self.assertEqual(str(then), '2003-02-01.00:00:00') now = Date('2005-02-01.00:00:00') then = now - Interval('365d') self.assertEqual(str(then), '2004-02-02.00:00:00')
def month_links(self): """ Return month name with links to prev/next month """ pms = self.fdd - Interval('1m') nms = self.fdd + Interval('1m') pme = common.end_of_month(pms) nme = common.end_of_month(nms) return ' '.join \ (( self.month_link (pms, pme, '<<') , self.month , str (self.fdd.year) , self.month_link (nms, nme, '>>') ))
def iv_filter(self, ids): """ Filter invoices for - invoice belongs to a running subscription - invoice is in the correct self.invoice_group - correct interval: We do not want to send invoices before the interval of the invoice_template has expired after sending the last invoice (last_sent < now - interval) where interval is in months """ db = self.db retval = [] for id in ids: iv = self.db.invoice.getnode(id) abo = self.db.abo.getnode(iv['abo']) if abo['end']: continue grp = self.db.abo_price.get(abo['aboprice'], 'invoice_group') if grp != self.invoice_group: continue ivt = self.get_iv_template(iv) interval = ivt['interval'] if iv['last_sent'] > self.now - Interval('%dm' % interval): continue retval.append(iv) return retval
def create_daily_records (self) : self.set_request () request = self.request filterspec = request.filterspec columns = request.columns assert (request.classname == 'daily_record') start, end = common.date_range (self.db, filterspec) self.start = start self.end = end max = start + Interval ('31d') if end > max : msg = \ ( "Error: Interval may not exceed one month: %s" % ' to '.join ([i.pretty (common.ymd) for i in (start, end)]) ) end = max request.filterspec ['date'] = common.pretty_range (start, end) url = request.indexargs_url \ ( '' , { ':action' : 'search' , ':template' : 'edit' , ':sort' : 'date' , ':group' : 'user' , ':filter' : ','.join (request.filterspec.keys ()) , ':startwith' : '0' , ':error_message' : msg } ) raise Redirect, url if 'user' in filterspec : self.user = filterspec ['user'][0] else : self.user = self.db.getuid () vacation.create_daily_recs (self.db, self.user, start, end) self.db.commit ()
def next_week (db, request) : try : db = db._db except AttributeError : pass start, end = common.date_range (db, request.filterspec) n_start = end + Interval ('1d') n_end = n_start + Interval ('6d') date = common.pretty_range (n_start, n_end) return \ '''javascript: if(submit_once()) { document.forms.edit_daily_record ['date'].value = '%s'; document.edit_daily_record.submit (); } ''' % date
def check_range(db, nodeid, uid, first_day, last_day): """ Check length of range and if there are any records in the given time-range for this user. This means either the first day of an existing record is inside the new range or the last day is inside the new range or the first day is lower than the first day *and* the last day is larger (new interval is contained in existing interval). """ if first_day > last_day: raise Reject(_("First day may not be after last day")) if (last_day - first_day) > Interval('30d'): raise Reject(_("Max. 30 days for single leave submission")) range = common.pretty_range(first_day, last_day) both = (first_day.pretty(';%Y-%m-%d'), last_day.pretty('%Y-%m-%d;')) stati = [ x for x in db.leave_status.getnodeids(retired=False) if db.leave_status.get(x, 'name') not in ('declined', 'cancelled') ] for f, l in ((range, None), (None, range), both): d = dict(user=uid, status=stati) if f: d['first_day'] = f if l: d['last_day'] = l r = [x for x in db.leave_submission.filter(None, d) if x != nodeid] if r: raise Reject \ (_ ("You already have vacation requests in this time range"))
def init(instance): reg = instance.registerUtil reg('valid_wps', vacation.valid_wps) reg('valid_leave_wps', vacation.valid_leave_wps) reg('valid_leave_projects', vacation.valid_leave_projects) reg('leave_days', leave_days) reg('user_leave_submissions', user_leave_submissions) reg('approve_leave_submissions', approve_leave_submissions) reg('approve_leave_submissions_hr', approve_leave_submissions_hr) reg('Leave_Buttons', Leave_Buttons) reg('remaining_until', remaining_until) reg('remaining_vacation', remaining_vacation) reg('consolidated_vacation', consolidated_vacation) reg('vacation_with_status', vacation_with_status) reg('flexitime_with_status', flexitime_with_status) reg('vacation_time_sum', vacation.vacation_time_sum) reg('get_vacation_correction', vacation.get_vacation_correction) reg('year', Interval('1y')) reg('day', common.day) reg('eoy_vacation', eoy_vacation) reg('Leave_Display', Leave_Display) reg('month_name', month_name) reg('flexi_alliquot', vacation.flexi_alliquot) reg('flexi_remain', vacation.flexi_remain) reg('avg_hours_per_week_this_year', avg_hours) reg('get_current_ctype', vacation.get_current_ctype) action = instance.registerAction action('new_leave', New_Leave_Action)
def testOffsetRandom(self): ae = self.assertEqual # XXX unsure of the usefulness of these, they're pretty random date = Date('2000-01-01') + Interval('- 2y 2m') ae(str(date), '1997-11-01.00:00:00') date = Date('2000-01-01 - 2y 2m') ae(str(date), '1997-11-01.00:00:00') date = Date('2000-01-01') + Interval('2m') ae(str(date), '2000-03-01.00:00:00') date = Date('2000-01-01 + 2m') ae(str(date), '2000-03-01.00:00:00') date = Date('2000-01-01') + Interval('60d') ae(str(date), '2000-03-01.00:00:00') date = Date('2001-01-01') + Interval('60d') ae(str(date), '2001-03-02.00:00:00')
def dr_freeze_last_frozen (db, userid, itemid) : """User is allowed to edit freeze record if not frozen at the given date. Check that no daily_record_freeze is active after date """ df = db.daily_record_freeze.getnode (itemid) return not frozen (db, df.user, df.date + Interval ('1d'))
def testIntervalSubtractMonthBoundary(self): # force the transition over a month boundary now = Date('2003-11-01.00:00:00') then = now - Interval('2d') self.assertEqual(str(then), '2003-10-30.00:00:00') now = Date('2004-02-29.00:00:00') then = now - Interval('1d') self.assertEqual(str(then), '2004-02-28.00:00:00') now = Date('2003-03-01.00:00:00') then = now - Interval('1d') self.assertEqual(str(then), '2003-02-28.00:00:00') now = Date('2003-03-01.00:00:00') then = now - Interval('59d') self.assertEqual(str(then), '2003-01-01.00:00:00') now = Date('2004-02-29.00:00:00') then = now - Interval('59d') self.assertEqual(str(then), '2004-01-01.00:00:00')
def testIntervalInit(self): ae = self.assertEqual ae(str(Interval('3y')), '+ 3y') ae(str(Interval('2 y 1 m')), '+ 2y 1m') ae(str(Interval('1m 25d')), '+ 1m 25d') ae(str(Interval('-2w 3 d ')), '- 17d') ae(str(Interval(' - 1 d 2:50 ')), '- 1d 2:50') ae(str(Interval(' 14:00 ')), '+ 14:00') ae(str(Interval(' 0:04:33 ')), '+ 0:04:33') ae(str(Interval(8.*3600)), '+ 8:00')
def weeksum (db, drid, format = None) : start, end = common.week_from_date (db.daily_record.get (drid, 'date')) user = db.daily_record.get (drid, 'user') d = start sum = 0. while d <= end : dr = db.daily_record.filter \ (None, dict (date = common.pretty_range (d, d), user = user)) if len (dr) == 0 : d = d + Interval ('1d') continue assert (len (dr) == 1) dr = dr [0] sum += daysum (db, dr) d = d + Interval ('1d') if format : return format % sum return sum
def new_invoice(db, cl, nodeid, new_values): common.require_attributes(_, cl, nodeid, new_values, 'abo') abo_id = new_values.get('abo', None) abo = db.abo.getnode(abo_id) abo_price = db.abo_price.getnode(abo['aboprice']) abo_type = db.abo_type.getnode(abo_price['abotype']) common.reject_attributes \ ( _ , new_values , 'balance_open' , 'n_sent' , 'last_sent' , 'payer' , 'subscriber' , 'send_it' , 'period_start' , 'period_end' , 'invoice_no' , 'payment' , 'invoice_group' ) if 'amount' not in new_values: new_values['amount'] = abo['amount'] if 'currency' not in new_values: new_values['currency'] = abo_price['currency'] new_values['balance_open'] = new_values['amount'] new_values['open'] = new_values['balance_open'] > 0 new_values['n_sent'] = 0 new_values['payer'] = abo['payer'] new_values['subscriber'] = abo['subscriber'] new_values['send_it'] = False if not len(abo['invoices']): start = abo['begin'] else: maxinv = abo_max_invoice(db, abo) start = maxinv['period_end'] + Interval('1d') end = start + Interval('%dm' % abo_type['period']) end = end - Interval('1d') new_values['period_start'] = start new_values['period_end'] = end new_values['invoice_no'] = "R%s%s" % (abo_id, end.pretty('%m%y'))
def testCollision(self): # fake up an actual change self.action.classname = 'test' self.action.nodeid = '1' self.client.parsePropsFromForm = lambda: ({ ('test', '1'): { "prop1": "1" } }, []) props = self.action.detectCollision(self.now, self.now + Interval("1d")) self.assertTrue(props) self.action.handleCollision(props) self.assertEqual( self.client._error_message[0], 'Edit Error: someone else has edited this test ' '(prop1). View <a target="_blank" href="test1">their ' 'changes</a> in a new window.') self.assertFalse( self.action.detectCollision(self.now, self.now - Interval("1d"))) self.assertFalse(self.action.detectCollision(None, self.now))
def check_alarm (db, cl, nodeid, old_values) : m = cl.getnode (nodeid) s = db.sensor.getnode (m.sensor) now = Date ('.') for a_id in db.alarm.filter (None, dict (sensor = s.id)) : a = db.alarm.getnode (a_id) # default 1h for timeout timeout = Interval ((a.timeout or 0) * 60 or '01:00:00') if not a.last_triggered or a.last_triggered + timeout < now : if a.is_lower and m.val < a.val : notify (db, a, s, m, now, a.is_lower) if not a.is_lower and m.val > a.val : notify (db, a, s, m, now, a.is_lower)
def testIntervalInitDate(self): ae = self.assertEqual now = Date('.') now.hour = now.minute = now.second = 0 then = now + Interval('2d') ae((Interval(str(then))), Interval('- 2d')) then = now - Interval('2d') ae(Interval(str(then)), Interval('+ 2d'))
def testDateSubtract(self): # These are thoroughly broken right now. i = Date('2003-03-15.00:00:00') - Date('2003-03-10.00:00:00') self.assertEqual(i, Interval('5d')) i = Date('2003-02-01.00:00:00') - Date('2003-03-01.00:00:00') self.assertEqual(i, Interval('-28d')) i = Date('2003-03-01.00:00:00') - Date('2003-02-01.00:00:00') self.assertEqual(i, Interval('28d')) i = Date('2003-03-03.00:00:00') - Date('2003-02-01.00:00:00') self.assertEqual(i, Interval('30d')) i = Date('2003-03-03.00:00:00') - Date('2002-02-01.00:00:00') self.assertEqual(i, Interval('395d')) i = Date('2003-03-03.00:00:00') - Date('2003-04-01.00:00:00') self.assertEqual(i, Interval('-29d')) i = Date('2003-03-01.00:00:00') - Date('2003-02-01.00:00:00') self.assertEqual(i, Interval('28d')) # force the transition over a year boundary i = Date('2003-01-01.00:00:00') - Date('2002-01-01.00:00:00') self.assertEqual(i, Interval('365d')) i = Date('1952-01-01') - Date('1953-01-01') self.assertEqual(i, Interval('-366d')) i = Date('1953-01-01') - Date('1952-01-01') self.assertEqual(i, Interval('366d'))
def testOffsetAdd(self): ae = self.assertEqual date = Date('2000-02-28.23:59:59') + Interval('00:00:01') ae(str(date), '2000-02-29.00:00:00') date = Date('2001-02-28.23:59:59') + Interval('00:00:01') ae(str(date), '2001-03-01.00:00:00') date = Date('2000-02-28.23:58:59') + Interval('00:01:01') ae(str(date), '2000-02-29.00:00:00') date = Date('2001-02-28.23:58:59') + Interval('00:01:01') ae(str(date), '2001-03-01.00:00:00') date = Date('2000-02-28.22:58:59') + Interval('01:01:01') ae(str(date), '2000-02-29.00:00:00') date = Date('2001-02-28.22:58:59') + Interval('01:01:01') ae(str(date), '2001-03-01.00:00:00') date = Date('2000-02-28.22:58:59') + Interval('00:00:3661') ae(str(date), '2000-02-29.00:00:00') date = Date('2001-02-28.22:58:59') + Interval('00:00:3661') ae(str(date), '2001-03-01.00:00:00') date = Date('2001-03-01.00:00:00') + Interval('150y') ae(str(date), '2151-03-01.00:00:00')
def testSorting(self): ae = self.assertEqual i1 = Interval('1y') i2 = Interval('1d') l = [i1, i2]; l.sort() ae(l, [i2, i1]) l = [i2, i1]; l.sort() ae(l, [i2, i1]) i1 = Interval('- 2d') i2 = Interval('1d') l = [i1, i2]; l.sort() ae(l, [i1, i2]) i1 = Interval("1:20") i2 = Interval("2d") i3 = Interval("3:30") l = [i1, i2, i3]; l.sort() ae(l, [i1, i3, i2])
def consolidated_vacation \ (db, user, ctype = -1, date = None, vc = None, to_eoy = True) : """ Compute remaining vacation on the given date """ if date is None : date = Date ('.') if ctype == -1 : ctype = _get_ctype (db, user, date) if ctype == -1 : return vc = vc or get_vacation_correction (db, user, ctype, date) if not vc : return None ed = next_yearly_vacation_date (db, user, ctype, date) if not to_eoy : ed = min (ed, date + common.day) d = vc.date dyn = vac_get_user_dynamic (db, user, ctype, d) while dyn and dyn.valid_to and dyn.valid_to <= d : dyn = vac_next_user_dynamic (db, dyn) if dyn is None : return None vac = float (vc.days) msg = "vac_aliq None for user_dynamic%s" % dyn.id assert dyn.vac_aliq, msg va = db.vac_aliq.getnode (dyn.vac_aliq) assert va.name in ('Daily', 'Monthly') # Need to skip first period without a dyn user record # sd is the current start date for german aliquotation # We subtract 1 day to easily compare the day of the ending-date # with the day of the start date sd = d # This is used for corrections if the start day lies beyond 28 -- in # that case there are months that simply don't have that date. So we # must correct for this in months with less days. sd_day = 0 if dyn.valid_from > d : sd = d = dyn.valid_from while dyn and d < ed : if dyn.valid_from > d : # We want to check if the days that are lost here whenever a # jump in dyn user records occurs are OK for monthly aliqotation sd = d = dyn.valid_from continue assert not dyn.valid_to or dyn.valid_to > d eoy = Date ('%s-12-31' % d.year) msg = "vacation_yearly None for user_dynamic%s" % dyn.id assert dyn.vacation_yearly is not None, msg msg = ( "vac_aliq changes w/o absolute vac_corr for user_dynamic%s" % dyn.id ) assert dyn.vac_aliq == va.id, msg if dyn.valid_to and dyn.valid_to <= ed and dyn.valid_to < eoy : if va.name == 'Daily' : yd = float (common.ydays (dyn.valid_to)) vac += interval_days \ (dyn.valid_to - d) * dyn.vacation_yearly / yd else : md = month_diff (sd, dyn.valid_to) dy = sd_day or sd.day if dyn.valid_to.day < dy : md -= 1 # Example: sd = 2018-04-03 valid_to = 2018-06-01 # Need to set sd=2018-05-03, i.e. the next start # day before valid_to # Even more complex is the case where e.g. # sd = 2018-03-31 valid_to = 2018-05-01 # We set sd=2018-04-30 and sd_day=31 # Get last day of last month lm = dyn.valid_to - Interval ('%sd' % dyn.valid_to.day) em = common.end_of_month (lm) if dy > em.day : sd_day = sd.day sd = em else : sd = Date (lm.pretty ("%%Y-%%m-%s" % sd.day)) sd_day = 0 else : sd = Date (dyn.valid_to.pretty ("%%Y-%%m-%s" % sd.day)) sd_day = 0 d = dyn.valid_to vac += dyn.vacation_yearly * md / 12.0 dyn = vac_next_user_dynamic (db, dyn) elif eoy < ed : if va.name == 'Daily' : yd = float (common.ydays (eoy)) iv = eoy + common.day - d vac += interval_days (iv) * dyn.vacation_yearly / yd else : md = month_diff (sd, eoy) dy = sd_day or sd.day assert eoy.day >= dy if dy == 1 : md += 1 sd = eoy + common.day else : sd = Date (eoy.pretty ("%%Y-%%m-%s" % sd.day)) sd_day = 0 vac += dyn.vacation_yearly * md / 12.0 d = eoy + common.day if dyn.valid_to == d : dyn = vac_next_user_dynamic (db, dyn) else : if va.name == 'Daily' : yd = float (common.ydays (ed - common.day)) vac += interval_days (ed - d) * dyn.vacation_yearly / yd else : md = month_diff (sd, ed) dy = sd_day or sd.day if ed.day < dy : md -= 1 sd = ed vac += dyn.vacation_yearly * md / 12.0 d = ed return vac
def testIntervalSub(self): ae = self.assertEqual ae(str(Interval('1y') - Interval('- 1y')), '+ 2y') ae(str(Interval('1y') - Interval('- 1m')), '+ 1y 1m') ae(str(Interval('1y') - Interval('- 2:40')), '+ 1y 2:40') ae(str(Interval('1y') - Interval('1y')), '00:00') ae(str(Interval('1y') - Interval('1m')), '+ 11m') ae(str(Interval('1:00') - Interval('- 1:00')), '+ 2:00') ae(str(Interval('0:50') - Interval('- 0:50')), '+ 1:40') ae(str(Interval('1:50') - Interval('1:50')), '00:00') ae(str(Interval('1:59:59') - Interval('- 00:00:01')), '+ 2:00') ae(str(Interval('2:00') - Interval('00:00:01')), '+ 1:59:59')
class Freeze_Action (Action, autosuper) : user_required_msg = ''"User is required" user_invalid_msg = ''"Invalid User" def get_user (self) : self.request = templating.HTMLRequest (self.client) user = self.request.form ['user'].value if not user : raise Reject, self._ (self.user_required_msg) try : self.user = self.db.user.lookup (user) except KeyError : raise Reject, self._ (self.user_invalid_msg) return self.user # end def get_user def handle (self) : if not self.request.form ['date'].value : raise Reject, self._ ("Date is required") self.date = Date (self.request.form ['date'].value) msg = [] for u in self.users : date = self.date dyn = user_dynamic.get_user_dynamic (self.db, u, date) if not dyn : dyn = user_dynamic.find_user_dynamic \ (self.db, u, date, direction = '-') if dyn : # there must be a valid_to date, otherwise # get_user_dynamic would have found something above date = dyn.valid_to - common.day assert (date < self.date) if dyn : try : self.db.daily_record_freeze.create \ (date = date, user = u, frozen = 1) except Reject, cause : msg.append ((str (cause), u)) self.db.commit () if msg : msg.sort () old = None o_u = None count = 1 new_m = [] msg.append ((None, None)) for m, u in msg : if m == old : count += 1 else : if old : if count > 1 : new_m.append ('%s (%d)' % (old, count)) else : new_m.append \ ( '%s (%s)' % (old, self.db.user.get (o_u, 'username')) ) count = 1 old = m o_u = u msg = new_m [:10] msg = '@ok_message=Warning: ' + '<br>Warning: '.join (msg) + '&' else : msg = '' url = \ ( 'daily_record_freeze?' + msg + ':columns=id,date,user,frozen,balance,validity_date' + '&:sort=user,date&:filter=creation' + '&:pagesize=200&:startwith=0&creation=%s%%3B' ) % (Date ('.') - Interval ('00:05')) raise Redirect, url
def approvals_pending (db, request, userlist) : try : db = db._db except AttributeError : pass pending = {} submitted = db.daily_record_status.lookup ('submitted') spec = copy (request.filterspec) filter = request.filterspec editdict = {':template' : 'edit', ':filter' : 'user,date'} now = Date ('.') for u in userlist : find_user = dict (user = u, status = submitted) fdate = None last_frozen = db.daily_record_freeze.filter \ ( None , dict (user = u, date = now.pretty (';%Y-%m-%d'), frozen = True) , group = [('-', 'date')] ) if last_frozen : fdate = db.daily_record_freeze.get (last_frozen [0], 'date') \ + common.day find_user ['date'] = fdate.pretty ('%Y-%m-%d;') dr_per_user = db.daily_record.filter (None, find_user) pending [u] = {} if dr_per_user : earliest = latest = None for p in dr_per_user : date = db.daily_record.get (p, 'date') week, year = common.weekno_year_from_day (date) if not earliest or date < earliest : earliest = date if not latest or date > latest : latest = date start, end = common.week_from_date (date) if fdate and start < fdate : start = fdate filter ['date'] = common.pretty_range (start, end) filter ['user'] = u pending [u][(year, week)] = \ [ None , request.indexargs_url ('', editdict) , 'todo' ] interval = latest - earliest for k in pending [u].iterkeys () : if interval < Interval ('31d') : filter ['date'] = common.pretty_range (earliest, latest) pending [u][k][0] = request.indexargs_url ('', editdict) else : pending [u][k][0] = pending [u][k][1] else : dyn = user_dynamic.last_user_dynamic (db, u) if dyn and (not dyn.valid_to or not fdate or dyn.valid_to > fdate) : date = now if dyn.valid_to and dyn.valid_to < date : date = dyn.valid_to week, year = common.weekno_year_from_day (date) start, end = common.week_from_date (date) if fdate and start < fdate : start = fdate if dyn.valid_to and dyn.valid_to < end : end = dyn.valid_to filter ['date'] = common.pretty_range (start, end) filter ['user'] = u url = request.indexargs_url ('', editdict) pending [u][(year, week)] = [url, url, 'done'] request.filterspec = spec return pending
def testDivision(self): ae = self.assertEqual ae(str(Interval('1y')/2), '+ 6m') ae(str(Interval('1:00')/2), '+ 0:30') ae(str(Interval('00:01')/2), '+ 0:00:30')
def ae(spec, pretty): self.assertEqual(Interval(spec).pretty(), pretty)
def html_calendar (request) : """returns a html calendar. `request` the roundup.request object - @template : name of the template - form : name of the form to store back the date - property : name of the property of the form to store back the date - date : current date - display : when browsing, specifies year and month html will simply be a table. """ #print request.form date_str = request.form.getfirst ("date", ".") display = request.form.getfirst ("display", date_str) template = request.form.getfirst ("@template", "calendar") form = request.form.getfirst ("form") property = request.form.getfirst ("property") curr_date = Date (date_str) # to highlight display = Date (display) # to show year = display.year month = display.month day = display.day # for navigation date_prev_month = display + Interval ("-1m") date_next_month = display + Interval ("+1m") date_prev_year = display + Interval ("-1y") date_next_year = display + Interval ("+1y") res = [] res.append ("""<table class="calendar">""") base_link = "%s?@template=%s&property=%s&form=%s&date=%s" % \ (request.classname, template, property, form, curr_date) # navigation # month res.append (""" <tr>""") res.append (""" <td>""") res.append (""" <table width="100%" class="calendar_nav">""") res.append (""" <tr>""") link = base_link + "&display=%s" % date_prev_month res.append (""" <td><a href="%s"><</a></td>""" % link) res.append (""" <td>%s</td>""" % calendar.month_name [month]) link = base_link + "&display=%s" % date_next_month res.append (""" <td><a href="%s">></a></td>""" % link) # spacer res.append (""" <td width="100%"></td>""") # year link = base_link + "&display=%s" % date_prev_year res.append (""" <td><a href="%s"><</a></td>""" % link) res.append (""" <td>%s</td>""" % year) link = base_link + "&display=%s" % date_next_year res.append (""" <td><a href="%s">></a></td>""" % link) res.append (""" </tr>""") res.append (""" </table>""") res.append (""" </td>""") res.append (""" </tr>""") # the calendar res.append (""" <tr>""") res.append (""" <td>""") res.append (""" <table class="calendar_display">""") res.append (""" <tr class="weekdays">""") for day_ in calendar.weekheader (3).split () : res.append \ (""" <td>%s</td>""" % day_) res.append (""" </tr>""") for week_ in calendar.monthcalendar (year, month) : res.append \ (""" <tr>""") for day_ in week_ : link = "javascript:form[field].value = '%d-%02d-%02d'; " \ "window.close ();" % (year, month, day_) #print curr_date, day_, month, year if day_ == curr_date.day and \ month == curr_date.month and \ year == curr_date.year : # highlight style = "today" else : style = "" if day_ : res.append \ (""" <td class="%s"><a href="%s">%s</a></td>""" % (style, link, day_)) else : res.append \ (""" <td></td>""") res.append \ (""" </tr>""") res.append (""" </table>""") res.append (""" </tb>""") res.append (""" </tr>""") res.append ("""</table>""") return "\n".join (res)
def testOffsetSub(self): ae = self.assertEqual date = Date('2000-12-01') - Interval('- 1d') date = Date('2000-01-01') - Interval('- 2y 2m') ae(str(date), '2002-03-01.00:00:00') date = Date('2000-01-01') - Interval('2m') ae(str(date), '1999-11-01.00:00:00') date = Date('2000-03-01') - Interval('60d') ae(str(date), '2000-01-01.00:00:00') date = Date('2001-03-02') - Interval('60d') ae(str(date), '2001-01-01.00:00:00') date = Date('2000-02-29.00:00:00') - Interval('00:00:01') ae(str(date), '2000-02-28.23:59:59') date = Date('2001-03-01.00:00:00') - Interval('00:00:01') ae(str(date), '2001-02-28.23:59:59') date = Date('2000-02-29.00:00:00') - Interval('00:01:01') ae(str(date), '2000-02-28.23:58:59') date = Date('2001-03-01.00:00:00') - Interval('00:01:01') ae(str(date), '2001-02-28.23:58:59') date = Date('2000-02-29.00:00:00') - Interval('01:01:01') ae(str(date), '2000-02-28.22:58:59') date = Date('2001-03-01.00:00:00') - Interval('01:01:01') ae(str(date), '2001-02-28.22:58:59') date = Date('2000-02-29.00:00:00') - Interval('00:00:3661') ae(str(date), '2000-02-28.22:58:59') date = Date('2001-03-01.00:00:00') - Interval('00:00:3661') ae(str(date), '2001-02-28.22:58:59') date = Date('2001-03-01.00:00:00') - Interval('150y') ae(str(date), '1851-03-01.00:00:00')