# Implementation of the @date and @datetime klammers (date.k). Each takes # the current date and time, offset by the :days argument (positive is # future, negative is past), and formats it in the requested language. # # Language selection is two-level: the klammer's :lang argument overrides # the document-wide Language state variable (declared in sks/kutil/kutil.k, # default en; set it for a whole document with @@@state Language :value de). # # :number selects the purely numeric form instead — which is language- # specific in order, separator, and padding: en 5/15/1955 (month first, # unpadded), de 15.05.1955 (day first, zero-padded per DIN 5008). # # Languages are OWN TABLES, deliberately not locales: strftime's %B follows # the process-wide C locale, which must be generated on the host (the # containers ship minimal locale support) and is global mutable state in the # embedded interpreter — the same reason @table's :decimal is implemented by # character translation. Adding a language is adding one LANGUAGES entry: # twelve month names and the date pattern (day/month/year; the day carries # no leading zero). The time suffix ", HH:MM" is language-independent. import datetime as dt LANGUAGES = { 'en': { 'months': ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], 'date': '{day} {month} {year}', # 16 June 1910 'number': '{m}/{day}/{year}', # 6/16/1910 }, 'de': { 'months': ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'], 'date': '{day}. {month} {year}', # 16. Juni 1910 'number': '{dd}.{mm}.{year}', # 16.06.1910 (DIN 5008) }, } def offset(days): return dt.datetime.now() + dt.timedelta(days=days or 0) def language(K): """The language table for K: :lang argument, else the Language state variable, else English. Returns (table, error_text).""" code = getattr(K, 'lang', '') or getattr(K, 'Language', '') or 'en' if code not in LANGUAGES: return None, ('ERROR: @date/@datetime: unknown language "%s" ' '(available: %s)' % (code, ', '.join(sorted(LANGUAGES)))) return LANGUAGES[code], None def format_date(t, lang, number=False): pattern = lang['number'] if number else lang['date'] return pattern.format(day=t.day, m=t.month, dd='%02d' % t.day, mm='%02d' % t.month, month=lang['months'][t.month - 1], year=t.year) def date(K): lang, error = language(K) if error: return error return format_date(offset(K.days), lang, K.number) def datetime(K): lang, error = language(K) if error: return error t = offset(K.days) return format_date(t, lang, K.number) + ', %02d:%02d' % (t.hour, t.minute)