def display_date(start, end): """ Formates the date range given for display. """ timezone = settings().timezone() start = sedate.to_timezone(start, timezone) end = sedate.to_timezone(end, timezone) if end.microsecond != 999999: end -= timedelta(microseconds=1) if (start, end) == align_range_to_day(start, end): if start.date() == end.date(): return localize_date(start, long_format=False) else: return ' - '.join(( localize_date(start, long_format=False), localize_date(end, long_format=False) )) end += timedelta(microseconds=1) if start.date() == end.date(): return ' - '.join(( localize_date(start, long_format=True), localize_date(end, time_only=True) )) else: return ' - '.join(( localize_date(start, long_format=True), localize_date(end, long_format=True) ))
def display_date(start, end): """ Formates the date range given for display. """ timezone = settings().timezone() start = sedate.to_timezone(start, timezone) end = sedate.to_timezone(end, timezone) if end.microsecond != 999999: end -= timedelta(microseconds=1) if (start, end) == align_range_to_day(start, end): if start.date() == end.date(): return localize_date(start, long_format=False) else: return ' - '.join((localize_date(start, long_format=False), localize_date(end, long_format=False))) end += timedelta(microseconds=1) if start.date() == end.date(): return ' - '.join( (localize_date(start, long_format=True), localize_date(end, time_only=True))) else: return ' - '.join((localize_date(start, long_format=True), localize_date(end, long_format=True)))
def add_reservation(start, end, reservation): day = start.day used_days[day] = True end += timedelta(microseconds=1) start = sedate.to_timezone(start, timezone=timezone) end = sedate.to_timezone(end, timezone=timezone) start = utils.localize_date(start, time_only=True) end = utils.localize_date(end, time_only=True) context = resources[utils.string_uuid(reservation.resource)] reservation_lists = report[day][utils.string_uuid( reservation.resource )] reservation_lists[reservation.status].append( dict( start=start, end=end, email=reservation.email, data=reservation.data, timespans=json_timespans(start, end), id=reservation.id, token=reservation.token, quota=utils.get_reservation_quota_statement(reservation.quota), resource=context, ) )
def test_require_timezone_awareness(): naive = datetime(2014, 10, 26, 0, 0, 0) with pytest.raises(sedate.NotTimezoneAware): sedate.to_timezone(naive, 'UTC') with pytest.raises(sedate.NotTimezoneAware): sedate.is_whole_day(naive, naive, 'UTC') with pytest.raises(sedate.NotTimezoneAware): sedate.align_date_to_day(naive, 'UTC', 'up')
def display_end(self, timezone=None): end = rasterize_end(self.end, self.allocation.raster) end += timedelta(microseconds=1) return sedate.to_timezone( end, timezone or self.allocation.timezone )
def display_end(self, timezone=None): """Returns the end plus one microsecond in either the timezone given or the timezone on the allocation. """ end = self.end + timedelta(microseconds=1) return sedate.to_timezone(end, timezone or self.timezone)
def format_date(self, dt, format): """ Returns a readable version of the given date while automatically converting to the principals timezone if the date is timezone aware. """ if getattr(dt, 'tzinfo', None) is not None: dt = to_timezone(dt, self.principal.time_zone) return super(Layout, self).format_date(dt, format)
def update_model(self, model): """ Stores the form values on the page. """ # clear the recurrence to avoid updating all occurrences too much model.recurrence = '' model.title = self.title.data model.content = { 'description': self.description.data } model.location = self.location.data model.tags = self.tags.data model.timezone = 'Europe/Zurich' model.start = replace_timezone( datetime( self.start_date.data.year, self.start_date.data.month, self.start_date.data.day, self.start_time.data.hour, self.start_time.data.minute ), model.timezone ) end_date = self.start_date.data if self.end_time.data <= self.start_time.data: end_date += timedelta(days=1) model.end = replace_timezone( datetime( end_date.year, end_date.month, end_date.day, self.end_time.data.hour, self.end_time.data.minute ), model.timezone ) if self.weekly.data and self.end_date.data: until_date = to_timezone( replace_timezone( datetime( self.end_date.data.year, self.end_date.data.month, self.end_date.data.day, self.end_time.data.hour, self.end_time.data.minute ), model.timezone ), 'UTC' ) model.recurrence = ( "RRULE:FREQ=WEEKLY;WKST=MO;BYDAY={0};UNTIL={1}".format( ','.join(self.weekly.data), until_date.strftime('%Y%m%dT%H%M%SZ') ) ) model.meta = model.meta or {} model.meta['submitter_email'] = self.email.data
def apply_model(self, model): self.number.data = model.number self.name.data = model.name self.date_.data = model.date self.deadline.data = model.deadline # Convert the deadline from UTC to the local timezone if self.deadline.data: self.deadline.data = to_timezone( self.deadline.data, self.timezone.data).replace(tzinfo=None) if model.in_use: self.number.render_kw = {'readonly': True}
def get_date_range(self): if self.allocation.partly_available: return sedate.get_date_range( sedate.to_timezone( self.allocation.start, self.allocation.timezone ), self.start.data, self.end.data ) else: return self.allocation.start, self.allocation.end
def ensure_valid_dates(self): valid = True min_start = self.selected_period.execution_start min_end = self.selected_period.execution_end for index, d in enumerate(self.parsed_dates): start_date = to_timezone(d.start, self.timezone).date() end_date = to_timezone(d.end, self.timezone).date() if d.start > d.end: self.date_errors[index] = self.request.translate(_( "The end date must be after the start date" )) valid = False if start_date < min_start or min_end < start_date: self.date_errors[index] = self.request.translate(_( "The date is outside the selected period" )) valid = False if end_date < min_start or min_end < end_date: self.date_errors[index] = self.request.translate(_( "The date is outside the selected period" )) valid = False for subindex, subd in enumerate(self.parsed_dates): if index != subindex: if overlaps(d.start, d.end, subd.start, subd.end): self.date_errors[index] = self.request.translate(_( "The date overlaps with another in this occasion" )) valid = False if not valid and not self.dates.errors: self.dates.errors = [_("Date validation failed")] return valid
def as_ical(self, description=None, rrule=None, url=None): """ Returns the occurrence as iCalendar string. """ event = icalendar.Event() event.add("summary", self.title) event.add("dtstart", to_timezone(self.start, UTC)) event.add("dtend", to_timezone(self.end, UTC)) event.add("last-modified", self.modified or self.created or datetime.utcnow()) event["location"] = icalendar.vText(self.location) if description: event["description"] = icalendar.vText(description) if rrule: event["rrule"] = icalendar.vRecur(icalendar.vRecur.from_ical(rrule.replace("RRULE:", ""))) if url: event.add("url", url) cal = icalendar.Calendar() cal.add("prodid", "-//OneGov//onegov.event//") cal.add("version", "2.0") cal.add_component(event) return cal.to_ical()
def export_issue(self, request): """ Export all issues as XLSX. The exported file can be re-imported using the import-issues command line command. """ output = BytesIO() workbook = Workbook(output, { 'default_date_format': 'dd.mm.yy' }) datetime_format = workbook.add_format({'num_format': 'dd.mm.yy hh:mm'}) worksheet = workbook.add_worksheet() worksheet.name = request.translate(_("Issues")) worksheet.write_row(0, 0, ( request.translate(_("Year")), request.translate(_("Number")), request.translate(_("Date")), request.translate(_("Deadline")) )) timezone = request.app.principal.time_zone for index, issue in enumerate(self.query()): worksheet.write(index + 1, 0, issue.date.year) worksheet.write(index + 1, 1, issue.number) worksheet.write(index + 1, 2, issue.date) worksheet.write_datetime( index + 1, 3, to_timezone(issue.deadline, timezone).replace(tzinfo=None), datetime_format ) workbook.close() output.seek(0) response = Response() response.content_type = ( 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ) response.content_disposition = 'inline; filename={}-{}.xlsx'.format( request.translate(_("Issues")).lower(), datetime.utcnow().strftime('%Y%m%d%H%M') ) response.body = output.read() return response
def occurrence_dates(self, limit=True, localize=False): """ Returns the start dates of all occurrences. Returns non-localized dates per default. Limits the occurrences per default to this and the next year. """ occurrences = [self.start] if self.recurrence: occurrences = rrule.rrulestr(self.recurrence, dtstart=self.start) occurrences = list(map(lambda x: standardize_date(x, self.timezone), occurrences)) if localize: occurrences = list(map(lambda x: to_timezone(x, self.timezone), occurrences)) if limit: max_year = datetime.today().year + 1 occurrences = list(filter(lambda x: x.year <= max_year, occurrences)) return occurrences
def as_json_date(date): return to_timezone(date, self.timezone)\ .replace(tzinfo=None).isoformat()
def display_end(self, timezone=None): """Returns the end plus one microsecond (nicer display).""" end = self.end + timedelta(microseconds=1) return sedate.to_timezone(end, timezone or self.timezone)
def display_start(self, timezone=None): """Does nothing but to form a nice pair to display_end.""" return sedate.to_timezone(self.start, timezone or self.timezone)
def localized_start(self): """ The localized version of the start date/time. """ return to_timezone(self.start, self.timezone)
def display_start(self, timezone=None): """Returns the start in either the timezone given or the timezone on the allocation.""" return sedate.to_timezone(self.start, timezone or self.timezone)
def localized_end(self): """ The localized version of the end date/time. """ return to_timezone(self.end, self.timezone)
def display_start(self, timezone=None): start = rasterize_start(self.start, self.allocation.raster) return sedate.to_timezone( start, timezone or self.allocation.timezone )
def send_daily_ticket_statistics(request): today = replace_timezone(datetime.utcnow(), 'UTC') today = to_timezone(today, 'Europe/Zurich') if today.weekday() in (SAT, SUN): return args = {} # get the current ticket count collection = TicketCollection(request.app.session()) count = collection.get_count() args['currently_open'] = count.open args['currently_pending'] = count.pending args['currently_closed'] = count.closed # get tickets created yesterday or on the weekend end = datetime(today.year, today.month, today.day, tzinfo=today.tzinfo) if today.weekday() == MON: start = end - timedelta(days=2) else: start = end - timedelta(days=1) query = collection.query() query = query.filter(Ticket.created >= start) query = query.filter(Ticket.created <= end) args['opened'] = query.count() query = collection.query() query = query.filter(Ticket.modified >= start) query = query.filter(Ticket.modified <= end) query = query.filter(Ticket.state == 'pending') args['pending'] = query.count() query = collection.query() query = query.filter(Ticket.modified >= start) query = query.filter(Ticket.modified <= end) query = query.filter(Ticket.state == 'closed') args['closed'] = query.count() # render the email args['title'] = request.translate( _("${town} OneGov Cloud Status", mapping={ 'town': request.app.town.name }) ) args['layout'] = DefaultMailLayout(object(), request) args['is_monday'] = today.weekday() == MON args['town'] = request.app.town.name content = render_template('mail_daily_ticket_statistics.pt', request, args) # send one e-mail per user users = UserCollection(request.app.session()).query() users = users.options(undefer('data')) users = users.all() for user in users: if user.data and not user.data.get('daily_ticket_statistics'): continue request.app.send_email( subject=args['title'], receivers=(user.username, ), content=content )
def parse_datetime(dt): d = datetime.utcfromtimestamp(int(dt)) d = sedate.replace_timezone(d, 'UTC') d = sedate.to_timezone(d, 'Europe/Zurich') return d
def local_date(self): return to_timezone(self.date, 'Europe/Zurich')