コード例 #1
0
ファイル: utils.py プロジェクト: i18nHub/onegov.town
def parse_fullcalendar_request(request, timezone):
    """ Parses start and end from the given fullcalendar request. It is
    expected that no timezone is passed (the default).

    See `<http://fullcalendar.io/docs/timezone/timezone/>`_

    :returns: A tuple of timezone-aware datetime objects or (None, None).

    """
    start = request.params.get('start')
    end = request.params.get('end')

    if start and end:
        if 'T' in start:
            start = parse_datetime(start)
            end = parse_datetime(end)
        else:
            start = datetime.combine(parse_date(start), time(0, 0))
            end = datetime.combine(parse_date(end), time(23, 59, 59, 999999))

        start = sedate.replace_timezone(start, timezone)
        end = sedate.replace_timezone(end, timezone)

        return start, end
    else:
        return None, None
コード例 #2
0
ファイル: collections.py プロジェクト: OneGov/onegov.event
    def add(self, title, start, end, timezone, autoclean=True, **optional):
        """ Add a new event.

        A unique, URL-friendly name is created automatically for this event
        using the title and optionally numbers for duplicate names.

        Every time a new event is added, old, stale events are deleted unless
        disabled with the ``autoclean`` option.

        Returns the created event or None if already automatically deleted.
        """
        event = Event(
            state='initiated',
            title=title,
            start=replace_timezone(start, timezone),
            end=replace_timezone(end, timezone),
            timezone=timezone,
            name=self._get_unique_name(title),
            **optional
        )

        self.session.add(event)
        self.session.flush()

        if autoclean:
            self.remove_stale_events()

        return event
コード例 #3
0
    def filter_by_year(self, query):
        timezone = 'Europe/Zurich'

        start = sedate.replace_timezone(datetime(self.year, 1, 1), timezone)
        end = sedate.replace_timezone(datetime(self.year + 1, 1, 1), timezone)

        return query.filter(and_(
            start <= MissionReport.date, MissionReport.date < end
        ))
コード例 #4
0
ファイル: test_sedate.py プロジェクト: seantis/sedate
def test_get_date_range():
    assert sedate.get_date_range(
        sedate.replace_timezone(datetime(2015, 1, 1), 'Europe/Zurich'),
        datetime(2015, 1, 1, 12, 0).time(),
        datetime(2015, 1, 2, 11, 0).time(),
    ) == (
        sedate.replace_timezone(datetime(2015, 1, 1, 12, 0), 'Europe/Zurich'),
        sedate.replace_timezone(datetime(2015, 1, 2, 11, 0), 'Europe/Zurich'),
    )
コード例 #5
0
ファイル: event.py プロジェクト: i18nHub/onegov.town
    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
コード例 #6
0
ファイル: test_sedate.py プロジェクト: seantis/sedate
def test_align_range_to_day():
    assert sedate.align_range_to_day(
        start=sedate.replace_timezone(datetime(2015, 1, 1, 10, 0),
                                      'Europe/Zurich'),
        end=sedate.replace_timezone(datetime(2015, 1, 1, 11, 0),
                                    'Europe/Zurich'),
        timezone='Europe/Zurich') == (sedate.replace_timezone(
            datetime(2015, 1, 1), 'Europe/Zurich'),
                                      sedate.replace_timezone(
                                          datetime(2015, 1, 1, 23, 59, 59,
                                                   999999), 'Europe/Zurich'))
コード例 #7
0
ファイル: page.py プロジェクト: i18nHub/onegov.town
def view_news(self, request):

    layout = NewsLayout(self, request)
    years = self.years

    try:
        year = int(request.params["year"])
    except (ValueError, KeyError):
        year = years and years[0] or None

    query = self.news_query

    if year:
        start = replace_timezone(datetime(year, 1, 1), "UTC")
        query = query.filter(Page.created >= start)
        query = query.filter(Page.created < start.replace(year=year + 1))

    if request.is_logged_in:
        layout.editbar_links = list(self.get_editbar_links(request))
        children = query.all()
    else:
        children = request.exclude_invisible(query.all())

    return {
        "layout": layout,
        "title": self.title,
        "name": self.trait_messages[self.trait]["name"],
        "page": self,
        "children": children,
        "years": years,
        "current_year": year,
    }
コード例 #8
0
ファイル: security.py プロジェクト: OneGov/onegov.wtfs
def has_permission_scan_job(app, identity, model, permission):
    # Editors and members of groups may view and edit scan jobs within
    # the same group
    if identity.role in ('editor', 'member'):
        if identity.groupid:

            if permission in {ViewModel, EditModel}:
                if same_group(model, identity):
                    return True

            if permission is DeleteModel and identity.role == 'editor':
                if same_group(model, identity):
                    dt = model.dispatch_date

                    # editors of the same group may delete scan jobs up until
                    # 17:00 on the day before the dispatch
                    horizon = datetime(dt.year, dt.month, dt.day, 17)
                    horizon -= timedelta(days=1)
                    horizon = sedate.replace_timezone(horizon, 'Europe/Zurich')

                    now = sedate.utcnow()

                    return now <= horizon

    return permission in getattr(app.settings.roles, identity.role)
コード例 #9
0
ファイル: test_sedate.py プロジェクト: seantis/sedate
def test_standardize_aware_date():
    aware_date = sedate.replace_timezone(datetime(2014, 10, 1, 13, 30),
                                         'Europe/Zurich')

    normalized = sedate.standardize_date(aware_date, 'Europe/Zurich')

    assert normalized.tzname() == 'UTC'
    assert normalized.replace(tzinfo=None) == datetime(2014, 10, 1, 11, 30)
コード例 #10
0
ファイル: allocation.py プロジェクト: seantis/libres
    def set_start(self, start):
        if not start.tzinfo:
            assert self.timezone
            start = sedate.replace_timezone(start, self.timezone)

        if self.raster is not None:
            self._start = rasterize_start(start, self.raster)
        else:
            self._start = rasterize_start(start, MIN_RASTER)
コード例 #11
0
ファイル: allocation.py プロジェクト: seantis/libres
    def set_end(self, end):
        if not end.tzinfo:
            assert self.timezone
            end = sedate.replace_timezone(end, self.timezone)

        if self.raster is not None:
            self._end = rasterize_end(end, self.raster)
        else:
            self._end = rasterize_end(end, MIN_RASTER)
コード例 #12
0
ファイル: test_sedate.py プロジェクト: seantis/sedate
def test_align_date_to_day_up():
    unaligned = sedate.standardize_date(datetime(2012, 1, 24, 10), 'UTC')
    aligned = sedate.align_date_to_day(unaligned, 'Europe/Zurich', 'up')

    assert aligned.tzname() == 'UTC'
    assert aligned == sedate.standardize_date(
        datetime(2012, 1, 24, 23, 59, 59, 999999), 'Europe/Zurich')

    already_aligned = sedate.replace_timezone(
        datetime(2012, 1, 1, 23, 59, 59, 999999), 'Europe/Zurich')

    assert already_aligned == sedate.align_date_to_day(already_aligned,
                                                       'Europe/Zurich', 'up')
コード例 #13
0
def test_is_whole_day():
    assert sedate.is_whole_day(
        sedate.replace_timezone(
            datetime(2015, 6, 30), 'Europe/Zurich'),
        sedate.replace_timezone(
            datetime(2015, 7, 1), 'Europe/Zurich'),
        'Europe/Zurich'
    )

    assert sedate.is_whole_day(
        sedate.replace_timezone(
            datetime(2015, 6, 30), 'Europe/Zurich'),
        sedate.replace_timezone(
            datetime(2015, 6, 30, 23, 59, 59), 'Europe/Zurich'),
        'Europe/Zurich'
    )

    assert not sedate.is_whole_day(
        sedate.replace_timezone(
            datetime(2015, 6, 30), 'Europe/Zurich'),
        sedate.replace_timezone(
            datetime(2015, 6, 30, 1), 'Europe/Zurich'),
        'Europe/Zurich'
    )
    assert not sedate.is_whole_day(
        sedate.replace_timezone(
            datetime(2015, 6, 30), 'Europe/Zurich'),
        sedate.replace_timezone(
            datetime(2015, 6, 30, 23, 59, 58), 'Europe/Zurich'),
        'Europe/Zurich'
    )
    assert not sedate.is_whole_day(
        sedate.replace_timezone(
            datetime(2015, 6, 30, 0, 0, 0, 999), 'Europe/Zurich'),
        sedate.replace_timezone(
            datetime(2015, 6, 30, 23, 59, 59), 'Europe/Zurich'),
        'Europe/Zurich'
    )
コード例 #14
0
ファイル: cli.py プロジェクト: OneGov/onegov.winterthur
    def extract_date(mission):
        d = datetime.utcfromtimestamp(int(mission.date))
        d = sedate.replace_timezone(d, 'Europe/Zurich')

        time = mission.alert_time.replace('.', ':')
        time = time.replace(';', ':')
        time = time.replace('::', ':')

        if ':' in time:
            h, m = (int(v.strip('<>-')) for v in time.split(':'))
        else:
            h = int(time)
            m = 0

        d = d.replace(hour=h)
        d = d.replace(minute=m)

        return d
コード例 #15
0
ファイル: occurrence.py プロジェクト: i18nHub/onegov.town
def view_get_occurrence(self, request):
    """ View a single occurrence of an event. """

    layout = OccurrenceLayout(self, request)
    today = replace_timezone(as_datetime(date.today()), self.timezone)
    occurrences = self.event.occurrence_dates(localize=True)
    occurrences = list(filter(lambda x: x >= today, occurrences))
    description = linkify(self.event.description).replace('\n', '<br>')
    session = request.app.session()
    ticket = TicketCollection(session).by_handler_id(self.event.id.hex)

    return {
        'description': description,
        'layout': layout,
        'occurrence': self,
        'occurrences': occurrences,
        'ticket': ticket,
        'title': self.title,
    }
コード例 #16
0
ファイル: file.py プロジェクト: OneGov/onegov.file
 def signature_timestamp(self):
     if self.signed:
         return sedate.replace_timezone(
             isodate.parse_datetime(self.signature_metadata['timestamp']),
             'UTC'
         )
コード例 #17
0
ファイル: collections.py プロジェクト: OneGov/onegov.event
    def query(self, start=None, end=None, tags=None, outdated=False):
        """ Queries occurrences with the given parameters.

        Finds all occurrences with any of the given tags and within the given
        start and end date. Start and end date are assumed to be dates only and
        therefore without a timezone - we search for the given date in the
        timezone of the occurrence!.

        If no start date is given and ``outdated`` is not set, only current
        occurrences are returned.
        """

        query = self.session.query(Occurrence)

        if start is not None:
            assert type(start) is date
            start = as_datetime(start)

            expressions = []
            for timezone in self.used_timezones:
                localized_start = replace_timezone(start, timezone)
                localized_start = standardize_date(localized_start, timezone)
                expressions.append(
                    and_(
                        Occurrence.timezone == timezone,
                        Occurrence.start >= localized_start
                    )
                )

            query = query.filter(or_(*expressions))
        elif not outdated:
            start = as_datetime(date.today())

            expressions = []
            for timezone in self.used_timezones:
                localized_start = replace_timezone(start, timezone)
                localized_start = standardize_date(localized_start, timezone)
                expressions.append(
                    and_(
                        Occurrence.timezone == timezone,
                        Occurrence.start >= localized_start
                    )
                )

            query = query.filter(or_(*expressions))

        if end is not None:
            assert type(end) is date
            end = as_datetime(end)
            end = end + timedelta(days=1)

            expressions = []
            for timezone in self.used_timezones:
                localized_end = replace_timezone(end, timezone)
                localized_end = standardize_date(localized_end, timezone)
                expressions.append(
                    and_(
                        Occurrence.timezone == timezone,
                        Occurrence.end < localized_end
                    )
                )

            query = query.filter(or_(*expressions))

        if tags:
            query = query.filter(Occurrence._tags.has_any(array(tags)))

        query = query.order_by(Occurrence.start, Occurrence.title)

        return query
コード例 #18
0
def test_editor_delete_day_before(wtfs_app, wtfs_password):
    session = wtfs_app.session()

    def permits(user, model, permission):
        return permits_by_app(wtfs_app, user, model, permission)

    # Remove existing users and group
    session.query(User).delete()
    session.query(Municipality).delete()

    # Add two towns
    foo = uuid4()

    session.add(Municipality(
        id=foo,
        name='Foo',
        bfs_number=1,
    ))
    session.add(PickupDate(
        date=date.today(),
        municipality_id=foo,
    ))

    bar = uuid4()

    session.add(Municipality(
        id=bar,
        name='Bar',
        bfs_number=1,
    ))
    session.add(PickupDate(
        date=date.today(),
        municipality_id=bar,
    ))

    # add a single scan job to foo
    session.add(ScanJob(
        type='normal',
        municipality_id=foo,
        delivery_number=1,
        dispatch_date=date(2019, 1, 1))
    )

    # an admin with access to all of it
    session.add(User(
        username='******',
        password_hash=wtfs_password,
        role='admin'
    ))

    # an editor with access to foo
    session.add(User(
        username='******',
        password_hash=wtfs_password,
        role='editor',
        group_id=foo
    ))

    # a member with access to foo
    session.add(User(
        username='******',
        password_hash=wtfs_password,
        role='member',
        group_id=foo
    ))

    # an editor with access to bar
    session.add(User(
        username='******',
        password_hash=wtfs_password,
        role='editor',
        group_id=bar
    ))

    # a member with access to bar
    session.add(User(
        username='******',
        password_hash=wtfs_password,
        role='member',
        group_id=bar
    ))

    session.flush()

    def fetch_user(username):
        return session.query(User).filter_by(username=username).one()

    job = session.query(ScanJob).one()

    admin = fetch_user('*****@*****.**')
    foo_editor = fetch_user('*****@*****.**')
    foo_member = fetch_user('*****@*****.**')
    bar_editor = fetch_user('*****@*****.**')
    bar_member = fetch_user('*****@*****.**')

    dt = sedate.replace_timezone(datetime(2018, 12, 31), 'Europe/Zurich')

    with freeze_time(dt.replace(hour=17, minute=0)):
        assert permits(admin, job, DeleteModel)
        assert permits(foo_editor, job, DeleteModel)
        assert not permits(foo_member, job, DeleteModel)
        assert not permits(bar_editor, job, DeleteModel)
        assert not permits(bar_member, job, DeleteModel)

    with freeze_time(dt.replace(hour=17, minute=1)):
        assert permits(admin, job, DeleteModel)
        assert not permits(foo_editor, job, DeleteModel)
        assert not permits(foo_member, job, DeleteModel)
        assert not permits(bar_editor, job, DeleteModel)
        assert not permits(bar_member, job, DeleteModel)
コード例 #19
0
ファイル: cli.py プロジェクト: OneGov/onegov.wtfs
    def parse_datetime(dt):
        d = datetime.utcfromtimestamp(int(dt))
        d = sedate.replace_timezone(d, 'UTC')
        d = sedate.to_timezone(d, 'Europe/Zurich')

        return d
コード例 #20
0
ファイル: cronjobs.py プロジェクト: i18nHub/onegov.town
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
        )
コード例 #21
0
ファイル: test_models.py プロジェクト: OneGov/onegov.event
def tzdatetime(year, month, day, hour, minute, timezone):
    return replace_timezone(datetime(year, month, day, hour, minute), timezone)