I use Espanso (free, open-source) for this. I have a number of shortcuts:
-
;today
generates May 3, 2023
-
;fdate
or ;ddate
generates Wednesday, May 3, 2023
-
;now
or ;odate
generates 3rd day of May, 2023
-
;date
opens a dialog box where I can enter any date (in YYYY-MM-DD or MM-DD format) and select from any of the above formats. It then inserts the given date in the selected format.
Note that the last two require a Python script to work, although, you can use any scripting language. I just happen to prefer working in Python. I needed the script for ordinal dates (1st
, 2nd
, 3rd
, 4th
…), which I use regularly. If you don’t need that, then the script is not necessary.
The relevant section of my config file which implements the above looks like this:
# Today (January 1, 2021)
- trigger: ";today"
replace: "{{date}}"
vars:
- name: date
type: date
params:
format: "%B %e, %Y"
# Full/Day Date (Friday, January 1, 2021)
- triggers: [";fdate", ";ddate"]
replace: "{{ddate}}"
vars:
- name: ddate
type: date
params:
format: "%A, %B %e, %Y"
# Ordinal Date (1st day of January, 2021)
- triggers: [";now", ";odate"]
replace: "{{formated_date}}"
vars:
- name: dateform_format
type: echo
params:
echo: "Do [day of] MMMM, YYYY"
- name: formated_date
type: script
params:
args:
- python
- "%CONFIG%/scripts/format_date.py"
# Date from form
- trigger: ';date'
replace: "{{formated_date}}"
vars:
- name: dateform
type: form
params:
layout: |
Date: {{date}}
Format: {{format}}
fields:
format:
type: list
values:
- "MMMM D, YYYY"
- "dddd, MMMM D, YYYY"
- "Do [day of] MMMM, YYYY"
- name: formated_date
type: script
params:
args:
- python
- "%CONFIG%/scripts/format_date.py"
And this is my Python script:
import arrow
import re
import os
YEAR_RE = re.compile(r'^\d{4}')
def normalize(date_str):
sep = ''
if '/' in date_str:
sep = '/'
elif '-' in date_str:
sep = '-'
elif '.' in date_str:
sep = '.'
if len(date_str) < 6 and not YEAR_RE.match(date_str):
# Date is (probably) missing year. Use current year.
year = arrow.now().format('YYYY')
date_str = f'{year}{sep}{date_str}'
return date_str
def format_date(date_str, format):
date = arrow.get(normalize(date_str))
return date.format(format)
def get_args():
date = os.environ.get('ESPANSO_DATEFORM_DATE', arrow.now().format(arrow.FORMAT_RFC3339))
format = os.environ.get('ESPANSO_DATEFORM_FORMAT', 'MMMM D, YYYY')
return date, format
if __name__ == '__main__':
print(format_date(*get_args()))