Skip to content

Commit

Permalink
New date packages, date-offset and timezone-date (#147)
Browse files Browse the repository at this point in the history
* New date packages, `date-offset` and `timezone-date`

* Minor reformatting
  • Loading branch information
smeech authored Dec 28, 2024
1 parent 89ec1b3 commit 979749f
Show file tree
Hide file tree
Showing 7 changed files with 246 additions and 0 deletions.
26 changes: 26 additions & 0 deletions packages/date-offset/0.1.0/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Date Offsets

Espanso's inbuilt `date` extension is handy, but very limited, particularly because it **cannot** accept a `{{variable}}` for its `offset:` value.

This package contains short Espanso snippets to return dates offset from today, utilising the date-handling facilities of four different scripting languages, partly as an exercise for me in working out how this can be done.

As supplied, typing a trigger, e.g.:
```
-18d, +2w, -3m, +5y
```
will present you with a choice box, listing the different scripts, each of which will return the relevant (hopefully the same!) date.

Any of the languages you don't have installed will generate Espanso errors:
- Bash (Linux/macOS) or WSL (Windows)
- Powershell (Windows) or pwsh (Linux/macOS)
- Python
- Javascript

My tests (Linux) indicate that in speed, Bash > Python > Node > PowerShell, but PowerShell is likely to be faster (but not necessarily the *fastest*) in Windows.

Ultimately, adopt one and delete or comment-out the others you don't need.

See my package `timezone-date` for timezone offsets.

Stephen Meech
(@smeech)
7 changes: 7 additions & 0 deletions packages/date-offset/0.1.0/_manifest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
name: "date-offset"
title: "Date Offsets"
description: A package that uses the date-handling facilities of different scripting languages to return dates variably offset from today, as specified in a regex trigger.
homepage: "https://github.com/smeech"
version: 0.1.0
author: Stephen Meech
tags: [time, date, python, bash, powershell, pwsh, javascript, node.js]
88 changes: 88 additions & 0 deletions packages/date-offset/0.1.0/package.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/espanso/espanso/dev/schemas/match.schema.json


# Espanso snippets to return offset date from today
# Type e.g.: -18d, +2w, -3m, +5y etc.

matches:
# Bash version
- regex: (?P<offset>[+-]\d+)(?P<unit>[dwmy])
replace: "{{output}}"
label: Bash offset date
vars:
- name: output
type: shell
params:
shell: bash
cmd: |
case {{unit}} in
d) date=$(date -d "{{offset}} days" +"%d/%m/%y") ;;
w) date=$(date -d "{{offset}} weeks" +"%d/%m/%y") ;;
m) date=$(date -d "{{offset}} months" +"%d/%m/%y") ;;
y) date=$(date -d "{{offset}} years" +"%d/%m/%y") ;;
esac
echo "$date"
# PowerShell version
- regex: (?P<offset>[+-]\d+)(?P<unit>[dwmy])
replace: "{{output}}"
label: PowerShell offset date
vars:
- name: output
type: shell
params:
shell: pwsh
cmd: |
switch ("{{unit}}") {
"d" { $date = (Get-Date).AddDays({{offset}}).ToString("dd/MM/yy") }
"w" { $date = (Get-Date).AddDays({{offset}} * 7).ToString("dd/MM/yy") }
"m" { $date = (Get-Date).AddMonths({{offset}}).ToString("dd/MM/yy") }
"y" { $date = (Get-Date).AddYears({{offset}}).ToString("dd/MM/yy") }
}
Write-Output $date
# Python version
- regex: (?P<offset>[+-]\d+)(?P<unit>[dwmy])
replace: "{{output}}"
label: Python offset date
vars:
- name: output
type: script
params:
args:
- python
- -c
- |
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
now = datetime.now()
match "{{unit}}":
case "d": date = now + timedelta(days={{offset}})
case "w": date = now + timedelta(weeks={{offset}})
case "m": date = now + relativedelta(months={{offset}})
case "y": date = now + relativedelta(years={{offset}})
print(date.strftime("%d/%m/%y"))
# Javascript version
- regex: (?P<offset>[+-]\d+)(?P<unit>[dwmy])
replace: "{{output}}"
label: Javascript offset date
vars:
- name: output
type: script
params:
args:
- node
- -e
- |
let now = new Date();
switch('{{unit}}') {
case 'd': date = new Date(now.setDate(now.getDate() + {{offset}})); break;
case 'w': date = new Date(now.setDate(now.getDate() + ({{offset}} * 7))); break;
case 'm': date = new Date(now.setMonth(now.getMonth() + {{offset}})); break;
case 'y': date = new Date(now.setFullYear(now.getFullYear() + {{offset}})); break;
}
const day = ("0" + date.getDate()).slice(-2);
const month = ("0" + (date.getMonth() + 1)).slice(-2);
const year = date.getFullYear().toString().slice(-2);
console.log(`${day}/${month}/${year}`);
29 changes: 29 additions & 0 deletions packages/timezone-date/0.1.0/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Timezone Date

A single trigger that uses two Python scripts to offer a choice from the full set of worldwide timezones, returning the current date and time there.

(Espanso's inbuilt `date` extension is handy, but very limited, especially because it can't accept a `{{variable}}` for its `offset:` value. I'll publish another small package `date-offset` to illustrate other ways in which this can be done.)

Two versions of the match file are included:

1. `package.yml` uses the `pytz` library and should work with any version of Python
2. `_package.yml` uses `zoneinfo`, which is part of modern editions (v3.9+) of Python, and should be a few milliseconds faster

To try the latter, rename the first file to anything you like, with an underscore `_` as its first character so that Espanso ignores it, then *remove* the underscore prefixing the second file's name.

In the middle of each file is a `default:` line, currently:

```yml
default: Europe/London
```
Once you've tried the trigger, change this timezone value to take you quickly to a part of the list that suits you most - it's a long list!
There is scope to modify the code to:
- in the last line, change the text, and date format output
- hard-code a timezone into the third variable (if you only need one, for example), dispensing with the first two variables providing the choice
- include some sort of time offset (do so in the final section but *prior* to the conversion of UTC time to the specified timezone) - see also the `date-offset` package

Stephen Meech
(@smeech)
7 changes: 7 additions & 0 deletions packages/timezone-date/0.1.0/_manifest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
name: "timezone-date"
title: "Timezone Date"
description: A package that uses Python scripts to offer a choice from the full set of worldwide timezones, returning the current date and time there.
homepage: "https://github.com/smeech"
version: 0.1.0
author: Stephen Meech
tags: [time, date, timezone, python]
46 changes: 46 additions & 0 deletions packages/timezone-date/0.1.0/_package.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/espanso/espanso/dev/schemas/match.schema.json

# This version will work on newer (v3.9+) versions of Python
# and is probably faster than the one which relies on `pytz`

# To use it, rename this file, without the underscore `_` prefix
# and rename the other WITH an underscore prefix.

# Amend the `default: Europe/London` line 32 to suit yourself

matches:
- trigger: :tzdate
replace: '{{output}}'
vars:
- name: zones
type: script
params:
args:
- python
- -c
- |
from zoneinfo import available_timezones
print("\n".join(sorted(available_timezones())))
- name: zone_choice
type: form
params:
layout: 'Pick a time-zone: [[zone]]'
fields:
zone:
type: list
values: '{{zones}}'
default: Europe/London # Change this to a timezone that suits you
- name: output
type: script
params:
args:
- python
- -c
- |
from datetime import datetime; from zoneinfo import ZoneInfo
timezone = ZoneInfo('{{zone_choice.zone}}')
# Get the current UTC time
utc_now = datetime.utcnow()
# Convert UTC time to the specified timezone
local_time = utc_now.astimezone(timezone)
print("Current date and time in", timezone, "is:", local_time.strftime('%F %T'))
43 changes: 43 additions & 0 deletions packages/timezone-date/0.1.0/package.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/espanso/espanso/dev/schemas/match.schema.json

# This version should work on most versions of Python
# but may be slower than the one which uses `zoneinfo`

# Amend the `default: Europe/London` line 29 to your convenience

matches:
- trigger: :tzdate
replace: '{{output}}'
vars:
- name: zones
type: script
params:
args:
- python
- -c
- |
import pytz
print("\n".join(pytz.all_timezones))
- name: zone_choice
type: form
params:
layout: 'Pick a time-zone: [[zone]]'
fields:
zone:
type: list
values: '{{zones}}'
default: Europe/London # Change this to a timezone that suits you
- name: output
type: script
params:
args:
- python
- -c
- |
import pytz; from datetime import datetime
timezone = pytz.timezone('{{zone_choice.zone}}')
# Get the current date and time in UTC
utc_now = datetime.utcnow().replace(tzinfo=pytz.utc)
# Convert UTC time to the specified timezone
local_time = utc_now.astimezone(timezone)
print("Current date and time in", timezone, "is:", local_time.strftime('%F %T'))

0 comments on commit 979749f

Please sign in to comment.