def format_interval(start_dt, end_dt, locale=None, tz=None, date_skeletor="MEd", time_skeletor="Hm"): # XXX Finnish-specific if tz is None: tz = tzlocal() if locale is None: locale = get_current_locale() start_dt = start_dt.astimezone(tz) end_dt = end_dt.astimezone(tz) if start_dt.date() == end_dt.date(): interval_format = "{start_date} klo {start_time}–{end_time}" else: interval_format = "{start_date} klo {start_time} – {end_date} klo {end_time}" return interval_format.format( start_date=format_skeleton(date_skeletor, start_dt, locale=locale), start_time=format_skeleton(time_skeletor, start_dt, locale=locale), end_date=format_skeleton(date_skeletor, end_dt, locale=locale), end_time=format_skeleton(time_skeletor, end_dt, locale=locale), )
def test_format_skeleton(): dt = datetime(2007, 4, 1, 15, 30) assert (dates.format_skeleton('yMEd', dt, locale='en_US') == u'Sun, 4/1/2007') assert (dates.format_skeleton('yMEd', dt, locale='th') == u'อา. 1/4/2007') assert (dates.format_skeleton('EHm', dt, locale='en') == u'Sun 15:30') assert (dates.format_skeleton('EHm', dt, tzinfo=timezone('Asia/Bangkok'), locale='th') == u'อา. 22:30 น.')
def short_date_format(evt, locale=DEFAULT_LOCALE, user_tz: tzinfo = None) -> str: lo = Locale.parse(locale, sep='_') tz = get_timezone(evt.timezone) now = datetime.now() if evt.end: if evt.start.year != now.year or evt.end.year != evt.start.year: return format_interval(evt.start.date(), evt.end.date(), 'yMMMMd', tzinfo=tz, locale=lo) else: # Year can be skipped return format_interval(evt.start.date(), evt.end.date(), 'MMMd', tzinfo=tz, locale=lo) if evt.start.year != now.year: return format_skeleton('yMMMMd', evt.start, tzinfo=tz, locale=lo) else: # Year can be skipped return format_skeleton('MMMMd', evt.start, tzinfo=tz, locale=lo)
def full_date_format(evt, locale=DEFAULT_LOCALE, user_tz: tzinfo = None) -> str: """ full_date_format formats the date/time of an event. There are several things to keep in mind: - Events always have a start, but not always a specified end. - They might be just a range of dates (whole_day). - Events are located in some timezone. - If the consumer is in a different timezone than the event, it should be converted. - If the event is a whole day event, timezone should not be converted as this would bring dates out of alignment. - They should be displayed in a localized, but concise fashion, without unnecessary repetition. """ lo = Locale.parse(locale, sep='_') tz = get_timezone(evt.timezone) if evt.end: if evt.whole_day: return format_interval(evt.start.date(), evt.end.date(), 'yMMMMd', tzinfo=tz, locale=lo) else: if evt.start.date() == evt.end.date(): fmt = lo.datetime_formats['medium'].replace("'", "") return with_timezone( fmt.format( format_interval(evt.start.time(), evt.end.time(), 'Hm', tzinfo=tz, locale=lo), format_skeleton('yMMMMd', evt.start, tzinfo=tz, locale=lo)), evt, lo, user_tz) return with_timezone( format_interval(evt.start, evt.end, skeleton='yMMMMd Hm', tzinfo=tz, locale=lo), evt, lo, user_tz) # Event has no end date if evt.whole_day: return format_skeleton('yMMMMd', evt.start, tzinfo=tz, locale=lo) else: fmt = lo.datetime_formats['medium'].replace("'", "") return with_timezone( fmt.format( format_skeleton('Hm', evt.start, tzinfo=tz, locale=lo), format_skeleton('yMMMMd', evt.start, tzinfo=tz, locale=lo)), evt, lo, user_tz)
def format_yearmonth(yearmonth: str) -> str: """Format a year-month pair as a locale-dependent string.""" # Querying for yearmonth is easier (especially with sqlite3) and about the same speed, # even if we need to apply some more logic Python-side to make it look nice. year, month = map(int, yearmonth.split("-")) return format_skeleton("yMMMM", datetime.date(year, month, 1), locale=get_babel_locale())
def skeletonfmt(datetime=None, skeleton='yMEd', tz=None, locale=None): if tz is None: tz = tzlocal() if locale is None: locale = get_current_locale() datetime = datetime.astimezone(tz) return format_skeleton(skeleton, datetime, locale=locale)
def format_skeleton(self, skeleton, datetime=None, fuzzy=True): """Return a time and/or date formatted according to the given pattern In: - ``skeleton`` -- the pattern - ``datetime`` --a `time` or `datetime` object; if None, the current time in UTC is used - ``fuzzy`` -- If the skeleton is not found, allow choosing a skeleton that's close enough to it Returns: - the formatted time/date """ return dates.format_skeleton(skeleton, datetime, self.tzinfo, fuzzy, self)
def _format_edtf0_date(edtf_date, format, locale, strict): """Format an EDTF level 0 date.""" # Convert EDTFDate to a python Date dt = edtf_to_datetime(edtf_date, strict) if edtf_date.precision == PRECISION_DAY: # Day precision: use normal date formatter return format_date(dt.date(), format=format, locale=locale) else: # Year or month precision: Use skeleton formatting if format in ('full', 'long', 'medium', 'short'): skeleton = get_edtf_date_skeleton(edtf_date.precision, format) else: skeleton = format return format_skeleton(skeleton, datetime=dt, fuzzy=True, locale=locale)