mirror of
https://github.com/jbranchaud/til
synced 2026-07-06 17:20:33 +00:00
Compare commits
3 Commits
f2a6fddba8
...
01f9d89e8e
| Author | SHA1 | Date | |
|---|---|---|---|
| 01f9d89e8e | |||
| e1c3f23975 | |||
| 16ad6bd64d |
@@ -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).
|
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:
|
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)
|
- [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)
|
- [Look In Ruby Version Dotfile](mise/look-in-ruby-version-dotfile.md)
|
||||||
- [Override Your Project Mise File](mise/override-your-project-mise-file.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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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
|
# Create Umbrella Task For All Test Tasks
|
||||||
|
|
||||||
When I was first sketching out the [`mise`
|
When I was first sketching out the [`mise` tasks](https://mise.jdx.dev/tasks/running-tasks.html) for a Rails app, I added
|
||||||
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
|
||||||
the following two tasks. One is for running all the `rspec` tests. The Other is
|
|
||||||
for running all the `vitest` (JavaScript) tests.
|
for running all the `vitest` (JavaScript) tests.
|
||||||
|
|
||||||
```toml
|
```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
|
depends on all other `test:*` tasks, the tests will get run through those
|
||||||
dependencies.
|
dependencies.
|
||||||
|
|
||||||
This task naming pattern also allows for calling all tests with `mise run
|
This task naming pattern also allows for calling all tests with `mise run "test:**"`.
|
||||||
"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.
|
||||||
Reference in New Issue
Block a user