Ejemplo n.º 1
0
def age(
    dt: Optional[datetime],
    now: Optional[datetime] = None,
    add_direction: bool = True,
    date_threshold: Optional[Any] = None,
) -> str:
    """
    :param dt: :class:`datetime<datetime>` instance to format

    :param now: :class:`datetime<datetime>` instance to compare to `dt`

    :param add_direction: if `True`, will add "in" or "ago" (example for `en`
       locale) to time difference `dt - now`, i.e "in 9 min." or " 9min. ago"

    :param date_threshold: above threshold, will use a formated date instead of
       elapsed time indication. Supported values: "day".
    """
    # Fail silently for now XXX
    if not dt:
        return ""

    if not now:
        now = datetime.utcnow()

    locale = babel.get_locale()
    dt = utc_dt(dt)
    now = utc_dt(now)
    delta = dt - now

    if date_threshold is not None:
        dy, dw, dd = dt_cal = dt.isocalendar()
        ny, nw, nd = now_cal = now.isocalendar()

        if dt_cal != now_cal:
            # not same day
            remove_year = dy == ny
            date_fmt = locale.date_formats["long"].pattern
            time_fmt = locale.time_formats["short"].pattern
            fmt = locale.datetime_formats["medium"]

            if remove_year:
                date_fmt = date_fmt.replace("y", "").strip()
                # remove leading or trailing spaces, comma, etc...
                date_fmt = re.sub("^[^A-Za-z]*|[^A-Za-z]*$", "", date_fmt)

            fmt = fmt.format(time_fmt, date_fmt)
            return babel.format_datetime(dt, format=fmt)

    # don't use (flask.ext.)babel.format_timedelta: as of Flask-Babel 0.9 it
    # doesn't support "threshold" arg.
    return format_timedelta(
        delta,
        locale=locale,
        granularity="minute",
        threshold=0.9,
        add_direction=add_direction,
    )
Ejemplo n.º 2
0
def age(dt, now=None, add_direction=True, date_threshold=None):
    """
    :param dt: :class:`datetime<datetime.datetime>` instance to format

    :param now: :class:`datetime<datetime.datetime>` instance to compare to `dt`

    :param add_direction: if `True`, will add "in" or "ago" (example for `en`
       locale) to time difference `dt - now`, i.e "in 9 min." or " 9min. ago"

    :param date_threshold: above threshold, will use a formated date instead of
       elapsed time indication. Supported values: "day".
    """
    # Fail silently for now XXX
    if not dt:
        return ""

    if not now:
        now = datetime.datetime.utcnow()

    locale = babel.get_locale()
    dt = utc_dt(dt)
    now = utc_dt(now)
    delta = dt - now

    if date_threshold is not None:
        dy, dw, dd = dt_cal = dt.isocalendar()
        ny, nw, nd = now_cal = now.isocalendar()

        if dt_cal != now_cal:
            # not same day
            remove_year = dy == ny
            date_fmt = locale.date_formats["long"].pattern
            time_fmt = locale.time_formats["short"].pattern
            fmt = locale.datetime_formats["medium"]

            if remove_year:
                date_fmt = date_fmt.replace("y", "").strip()
                # remove leading or trailing spaces, comma, etc...
                date_fmt = re.sub("^[^A-Za-z]*|[^A-Za-z]*$", "", date_fmt)

            fmt = fmt.format(time_fmt, date_fmt)
            return babel.format_datetime(dt, format=fmt)

    # don't use (flask.ext.)babel.format_timedelta: as of Flask-Babel 0.9 it
    # doesn't support "threshold" arg.
    return format_timedelta(
        delta,
        locale=locale,
        granularity="minute",
        threshold=0.9,
        add_direction=add_direction,
    )
Ejemplo n.º 3
0
    def process_formdata(self, valuelist: List[str]) -> None:
        if valuelist:
            date_str = " ".join(valuelist)
            locale = get_locale()
            date_fmt = locale.date_formats["short"]
            date_fmt = babel2datetime(date_fmt)
            date_fmt = date_fmt.replace("%B", "%m").replace(
                "%b", "%m")  # force numerical months
            time_fmt = locale.time_formats["short"]
            time_fmt = babel2datetime(time_fmt)
            datetime_fmt = f"{date_fmt} | {time_fmt}"
            try:
                self.data = datetime.strptime(date_str, datetime_fmt)
                if not self.use_naive:
                    tz = get_timezone()
                    if self.data.tzinfo:
                        self.data = self.data.astimezone(tz)
                    else:
                        self.data = tz.localize(self.data)

                # convert to UTC
                self.data = utc_dt(self.data)
            except ValueError:
                self.data = None
                raise ValueError(self.gettext("Not a valid datetime value"))
Ejemplo n.º 4
0
  def process_formdata(self, valuelist):
    if valuelist:
      date_str = ' '.join(valuelist)
      locale = get_locale()
      date_fmt = locale.date_formats['short']
      date_fmt = babel2datetime(date_fmt)
      date_fmt = date_fmt.replace('%B', '%m')\
                         .replace('%b', '%m')  # force numerical months
      time_fmt = locale.time_formats['short']
      time_fmt = babel2datetime(time_fmt)
      datetime_fmt = u'{} | {}'.format(date_fmt, time_fmt)
      try:
        self.data = datetime.datetime.strptime(date_str, datetime_fmt)
        if not self.use_naive:
          tz = get_timezone()
          if self.data.tzinfo:
            self.data = self.data.astimezone(tz)
          else:
            self.data = tz.localize(self.data)

        # convert to UTC
        self.data = utc_dt(self.data)
      except ValueError:
        self.data = None
        raise ValueError(self.gettext('Not a valid datetime value'))
Ejemplo n.º 5
0
    def process_formdata(self, valuelist):
        if valuelist:
            date_str = " ".join(valuelist)
            locale = get_locale()
            date_fmt = locale.date_formats["short"]
            date_fmt = babel2datetime(date_fmt)
            date_fmt = date_fmt.replace("%B", "%m").replace(
                "%b", "%m"
            )  # force numerical months
            time_fmt = locale.time_formats["short"]
            time_fmt = babel2datetime(time_fmt)
            datetime_fmt = f"{date_fmt} | {time_fmt}"
            try:
                self.data = datetime.datetime.strptime(date_str, datetime_fmt)
                if not self.use_naive:
                    tz = get_timezone()
                    if self.data.tzinfo:
                        self.data = self.data.astimezone(tz)
                    else:
                        self.data = tz.localize(self.data)

                # convert to UTC
                self.data = utc_dt(self.data)
            except ValueError:
                self.data = None
                raise ValueError(self.gettext("Not a valid datetime value"))
Ejemplo n.º 6
0
 def set_cache_headers(self, response):
     if self.set_expire:
         response.cache_control.public = False
         response.cache_control.private = True
         response.cache_control.max_age = int(
             self.expire_offset.total_seconds())
         response.expires = utc_dt(datetime.utcnow() + self.expire_offset)
Ejemplo n.º 7
0
    def process_formdata(self, valuelist):
        if valuelist:
            date_str = ' '.join(valuelist)
            locale = get_locale()
            date_fmt = locale.date_formats['short']
            date_fmt = babel2datetime(date_fmt)
            date_fmt = date_fmt \
                .replace('%B', '%m') \
                .replace('%b', '%m')  # force numerical months
            time_fmt = locale.time_formats['short']
            time_fmt = babel2datetime(time_fmt)
            datetime_fmt = u'{} | {}'.format(date_fmt, time_fmt)
            try:
                self.data = datetime.datetime.strptime(date_str, datetime_fmt)
                if not self.use_naive:
                    tz = get_timezone()
                    if self.data.tzinfo:
                        self.data = self.data.astimezone(tz)
                    else:
                        self.data = tz.localize(self.data)

                # convert to UTC
                self.data = utc_dt(self.data)
            except ValueError:
                self.data = None
                raise ValueError(self.gettext('Not a valid datetime value'))
Ejemplo n.º 8
0
 def after_populate_obj(self):
   obj_meta = self.obj.meta.setdefault('abilian.core.models.comment', {})
   history = obj_meta.setdefault('history', [])
   history.append(dict(user_id=current_user.id,
                       user=unicode(current_user),
                       date=utc_dt(datetime.utcnow()).isoformat(),))
   self.obj.meta.changed()
Ejemplo n.º 9
0
 def set_cache_headers(self, response):
   """
   """
   if self.set_expire:
     response.cache_control.public = False
     response.cache_control.private = True
     response.cache_control.max_age = int(self.expire_offset.total_seconds())
     response.expires = utc_dt(datetime.utcnow() + self.expire_offset)
Ejemplo n.º 10
0
 def after_populate_obj(self):
     obj_meta = self.obj.meta.setdefault("abilian.core.models.comment", {})
     history = obj_meta.setdefault("history", [])
     history.append({
         "user_id": current_user.id,
         "user": text_type(current_user),
         "date": utc_dt(datetime.utcnow()).isoformat(),
     })
     self.obj.meta.changed()
Ejemplo n.º 11
0
    def process_data(self, value: datetime) -> None:
        if value is not None:
            if not value.tzinfo:
                if self.use_naive:
                    value = get_timezone().localize(value)
                else:
                    value = utc_dt(value)
            if not self.use_naive:
                value = value.astimezone(get_timezone())

        super().process_data(value)
Ejemplo n.º 12
0
    def process_data(self, value):
        if value is not None:
            if not value.tzinfo:
                if self.use_naive:
                    value = get_timezone().localize(value)
                else:
                    value = utc_dt(value)
            if not self.use_naive:
                value = value.astimezone(get_timezone())

        super().process_data(value)
Ejemplo n.º 13
0
 def after_populate_obj(self):
     obj_meta = self.obj.meta.setdefault("abilian.core.models.comment", {})
     history = obj_meta.setdefault("history", [])
     history.append(
         {
             "user_id": current_user.id,
             "user": str(current_user),
             "date": utc_dt(datetime.utcnow()).isoformat(),
         }
     )
     self.obj.meta.changed()
Ejemplo n.º 14
0
def datetimeparse(s):
    """Parse a string date time to a datetime object.

    Suitable for dates serialized with .isoformat()

    :return: None, or an aware datetime instance, tz=UTC.
    """
    try:
        dt = dateutil.parser.parse(s)
    except ValueError:
        return None

    return utc_dt(dt)
Ejemplo n.º 15
0
def datetimeparse(s) -> Optional[datetime]:
    """Parse a string date time to a datetime object.

    Suitable for dates serialized with .isoformat()

    :return: None, or an aware datetime instance, tz=UTC.
    """
    try:
        dt = dateutil.parser.parse(s)
    except ValueError:
        return None

    return utc_dt(dt)
Ejemplo n.º 16
0
    def after_populate_obj(self):
        session = sa.orm.object_session(self.obj)
        uploads = current_app.extensions["uploads"]
        self.obj.body_html = self.message_body
        obj_meta = self.obj.meta.setdefault("abilian.sbe.forum", {})
        history = obj_meta.setdefault("history", [])
        history.append(
            {
                "user_id": current_user.id,
                "user": str(current_user),
                "date": utc_dt(datetime.utcnow()).isoformat(),
                "reason": self.form.reason.data,
            }
        )
        self.obj.meta["abilian.sbe.forum"] = obj_meta  # trigger change for SA

        attachments_to_remove = []
        for idx in self.attachments_to_remove:
            try:
                idx = int(idx)
            except ValueError:
                continue

            if idx > len(self.obj.attachments):
                continue

            attachments_to_remove.append(self.obj.attachments[idx])

        for att in attachments_to_remove:
            session.delete(att)

        for handle in request.form.getlist("attachments"):
            fileobj = uploads.get_file(current_user, handle)
            if fileobj is None:
                continue

            meta = uploads.get_metadata(current_user, handle)
            name = meta.get("filename", handle)
            mimetype = meta.get("mimetype")

            if not isinstance(name, str):
                name = str(name, encoding="utf-8", errors="ignore")

            if not name:
                continue

            attachment = PostAttachment(name=name, post=self.obj)

            with fileobj.open("rb") as f:
                attachment.set_content(f.read(), mimetype)
            session.add(attachment)
Ejemplo n.º 17
0
    def after_populate_obj(self):
        session = sa.orm.object_session(self.obj)
        uploads = current_app.extensions['uploads']
        self.obj.body_html = self.message_body
        obj_meta = self.obj.meta.setdefault('abilian.sbe.forum', {})
        history = obj_meta.setdefault('history', [])
        history.append(
            dict(
                user_id=current_user.id,
                user=text_type(current_user),
                date=utc_dt(datetime.utcnow()).isoformat(),
                reason=self.form.reason.data,
            ))
        self.obj.meta['abilian.sbe.forum'] = obj_meta  # trigger change for SA

        attachments_to_remove = []
        for idx in self.attachments_to_remove:
            try:
                idx = int(idx)
            except ValueError:
                continue

            if idx > len(self.obj.attachments):
                continue

            attachments_to_remove.append(self.obj.attachments[idx])

        for att in attachments_to_remove:
            session.delete(att)

        for handle in request.form.getlist('attachments'):
            fileobj = uploads.get_file(current_user, handle)
            if fileobj is None:
                continue

            meta = uploads.get_metadata(current_user, handle)
            name = meta.get('filename', handle)
            mimetype = meta.get('mimetype')

            if not isinstance(name, text_type):
                name = text_type(name, encoding='utf-8', errors='ignore')

            if not name:
                continue

            attachment = PostAttachment(name=name, post=self.obj)

            with fileobj.open('rb') as f:
                attachment.set_content(f.read(), mimetype)
            session.add(attachment)
Ejemplo n.º 18
0
    def after_populate_obj(self):
        session = sa.orm.object_session(self.obj)
        uploads = current_app.extensions["uploads"]
        self.obj.body_html = self.message_body
        obj_meta = self.obj.meta.setdefault("abilian.sbe.forum", {})
        history = obj_meta.setdefault("history", [])
        history.append({
            "user_id": current_user.id,
            "user": text_type(current_user),
            "date": utc_dt(datetime.utcnow()).isoformat(),
            "reason": self.form.reason.data,
        })
        self.obj.meta["abilian.sbe.forum"] = obj_meta  # trigger change for SA

        attachments_to_remove = []
        for idx in self.attachments_to_remove:
            try:
                idx = int(idx)
            except ValueError:
                continue

            if idx > len(self.obj.attachments):
                continue

            attachments_to_remove.append(self.obj.attachments[idx])

        for att in attachments_to_remove:
            session.delete(att)

        for handle in request.form.getlist("attachments"):
            fileobj = uploads.get_file(current_user, handle)
            if fileobj is None:
                continue

            meta = uploads.get_metadata(current_user, handle)
            name = meta.get("filename", handle)
            mimetype = meta.get("mimetype")

            if not isinstance(name, text_type):
                name = text_type(name, encoding="utf-8", errors="ignore")

            if not name:
                continue

            attachment = PostAttachment(name=name, post=self.obj)

            with fileobj.open("rb") as f:
                attachment.set_content(f.read(), mimetype)
            session.add(attachment)
Ejemplo n.º 19
0
def seconds_since_epoch(dt):
    if not dt:
        return 0
    return int((utc_dt(dt) - EPOCH).total_seconds())
Ejemplo n.º 20
0
def seconds_since_epoch(dt):
    if not dt:
        return 0
    return int((utc_dt(dt) - EPOCH).total_seconds())