1
0
mirror of https://github.com/jbranchaud/til synced 2026-07-03 08:08:24 +00:00

Compare commits

...

3 Commits

Author SHA1 Message Date
jbranchaud 01f9d89e8e Add Parse Relative Time To datetime Object as a Python TIL 2026-03-08 10:53:04 -05:00
jbranchaud e1c3f23975 Add Pick From Tasks Using Interactive Picker as a Mise TIL 2026-03-07 23:40:52 -06:00
jbranchaud 16ad6bd64d Fix typo in old mise TIL 2026-03-07 17:03:44 -06:00
4 changed files with 106 additions and 6 deletions
+3 -1
View File
@@ -10,7 +10,7 @@ working across different projects via [VisualMode](https://www.visualmode.dev/).
For a steady stream of TILs, [sign up for my newsletter](https://visualmode.kit.com/newsletter).
_1753 TILs and counting..._
_1755 TILs and counting..._
See some of the other learning resources I work on:
@@ -763,6 +763,7 @@ If you've learned something here, support my efforts writing daily TILs by
- [List The Files Being Loaded By Mise](mise/list-the-files-being-loaded-by-mise.md)
- [Look In Ruby Version Dotfile](mise/look-in-ruby-version-dotfile.md)
- [Override Your Project Mise File](mise/override-your-project-mise-file.md)
- [Pick From Tasks Using Interactive Picker](mise/pick-from-tasks-using-interactive-picker.md)
- [Preserve Color Output For Task Command](mise/preserve-color-output-for-task-command.md)
- [Read Existing Dot Env File Into Env Vars](mise/read-existing-dot-env-file-into-env-vars.md)
- [Run A Command With Specific Tool Version](mise/run-a-command-with-specific-tool-version.md)
@@ -1052,6 +1053,7 @@ If you've learned something here, support my efforts writing daily TILs by
- [Keep A Tally With collections.Counter](python/keep-a-tally-with-collections-counter.md)
- [Load A File Into The Python REPL](python/load-a-file-into-the-python-repl.md)
- [Override The Boolean Context Of A Class](python/override-the-boolean-context-of-a-class.md)
- [Parse Relative Time To datetime Object](python/parse-relative-time-to-datetime-object.md)
- [Store And Access Immutable Data In A Tuple](python/store-and-access-immutable-data-in-a-tuple.md)
- [Test A Function With Pytest](python/test-a-function-with-pytest.md)
- [Use pipx To Install End User Apps](python/use-pipx-to-install-end-user-apps.md)
@@ -1,8 +1,7 @@
# Create Umbrella Task For All Test Tasks
When I was first sketching out the [`mise`
tasks](https://mise.jdx.dev/tasks/running-tasks.html) for a Rails app, I added
the following two tasks. One is for running all the `rspec` tests. The Other is
When I was first sketching out the [`mise` tasks](https://mise.jdx.dev/tasks/running-tasks.html) for a Rails app, I added
the following two tasks. One is for running all the `rspec` tests. The other is
for running all the `vitest` (JavaScript) tests.
```toml
@@ -49,5 +48,4 @@ Running `mise run test:all` won't execute its own command, but because it
depends on all other `test:*` tasks, the tests will get run through those
dependencies.
This task naming pattern also allows for calling all tests with `mise run
"test:**"`.
This task naming pattern also allows for calling all tests with `mise run "test:**"`.
@@ -0,0 +1,38 @@
# Pick From Tasks Using Interactive Picker
In [Add Mise Tasks For Common Workflow
Commands](https://www.visualmode.dev/add-mise-tasks-for-common-workflow-commands),
I wrote about a set of tasks I added as shortcuts for connecting to the `rails console` in various environments.
```toml
# mise.toml
[tasks."console:staging"]
description = "Open a Rails console on staging"
run = "ssh -t my-app-staging dokku run my-app rails console"
[tasks."console:prod"]
description = "Open a Rails console on production"
run = "ssh -t my-app-prod dokku run my-app rails console"
```
When a project is configured with multiple `mise` tasks like this, we can invoke
`mise run` without any specific arguments and it will prompt you with an
interactive picker. The picker will populate with all the tasks like so:
```bash
mise run
Tasks
Select a task to run
console:prod Open a Rails console on production
console:staging Open a Rails console on staging
/
esc clear filter • enter confirm
```
We can navigate between the options with the arrow keys (and if we exit _filter_
mode by hitting `esc`, then `j/k` also work to move down and up). While in
_filter_ mode, we can type into the prompt which will filter the list of
commands down to just the partial matches.
Once we're targeting the task we want to run, we hit `enter` and the task is
executed.
@@ -0,0 +1,62 @@
# Parse Relative Time To datetime Object
I was looking for an out-of-the-box solution for parsing natural language,
relative time strings (e.g. `'33 minutes ago'`) into valid `datetime` objects.
The best library for this is
[`dateparser`](https://dateparser.readthedocs.io/en/latest/).
While it is as easy to use this as _import_ then _parse_:
```python
>>> import dateparser
>>> dateparser.parse('33 minutes ago')
datetime.datetime(2026, 3, 7, 23, 19, 9, 17855)
```
There is more to it if we need to deal with timezones.
In my use case, I wanted to my `datetime` object to be timezone-aware and I
wanted to store it in `UTC`.
As is, the above simple `datetime` object is not `tzaware`, meaning it doesn't
have any `tzinfo` attached to it.
```python
>>> dateparser.parse('33 minutes ago').tzinfo is not None
False
```
We need to pass some additional settings during `parse`.
```python
>>> settings = {'RETURN_AS_TIMEZONE_AWARE': True}
>>> dateparser.parse('33 minutes ago', settings=settings)
>>> _
datetime.datetime(2026, 3, 8, 9, 53, 36, 225099, tzinfo=zoneinfo.ZoneInfo(key='America/Chicago'))
>>> settings['TO_TIMEZONE'] = 'UTC'
>>> dateparser.parse('33 minutes ago', settings=settings)
>>> _
datetime.datetime(2026, 3, 8, 14, 54, 47, 34041, tzinfo=<StaticTzInfo 'UTC'>)
```
The first step to getting a `datetime` object that is `tzaware` is to set
`RETURN_AS_TIMEZONE_AWARE` to `True`. That picks up the locale setting of the
system it is running on -- in my case, I'm in Chicago.
I said I wanted to store this as UTC though. That means I need to pass an
additional setting `TO_TIMEZONE` with a value of `'UTC'` which will translate
the `datetime` from my local time to UTC -- notice the 5 hour difference from
`9` to `14`.
Storing `datetime` details like this with timezone info _as_ UTC is nice because
it keeps everything consistent at the storage layer and then at the presentation
layer I can always convert it right back to the local timezone with
`astimezone`.
```python
>>> _.astimezone()
datetime.datetime(2026, 3, 8, 9, 54, 47, 34041, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=68400), 'CDT'))
```
See the [`datetime` docs](https://docs.python.org/3/library/datetime.html) for
more details.