custom date/time formats
This commit is contained in:
parent
d67e2d458a
commit
83b2397c87
|
|
@ -964,21 +964,45 @@ def get_template_content(notes_dir: str, template_name: str) -> Optional[str]:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
# Matches custom strftime placeholders like {{date:%Y%m%d}} or {{time:%H%M%S}}.
|
||||||
|
# The three prefixes mirror the bare {{date}}, {{time}}, {{datetime}} placeholders;
|
||||||
|
# disallowing '{' and '}' inside the format keeps parsing unambiguous and
|
||||||
|
# guarantees we never swallow an adjacent placeholder.
|
||||||
|
_STRFTIME_PLACEHOLDER_RE = re.compile(r'\{\{(date|time|datetime):([^{}]+)\}\}')
|
||||||
|
|
||||||
|
|
||||||
def apply_template_placeholders(content: str, note_path: str) -> str:
|
def apply_template_placeholders(content: str, note_path: str) -> str:
|
||||||
"""
|
"""
|
||||||
Replace template placeholders with actual values.
|
Replace template placeholders with actual values.
|
||||||
|
|
||||||
Supported placeholders:
|
Built-in named placeholders (fixed default formats):
|
||||||
{{date}} - Current date (YYYY-MM-DD)
|
{{date}} - Current date (YYYY-MM-DD)
|
||||||
{{time}} - Current time (HH:MM:SS)
|
{{time}} - Current time (HH:MM:SS)
|
||||||
{{datetime}} - Current datetime (YYYY-MM-DD HH:MM:SS)
|
{{datetime}} - Current datetime (YYYY-MM-DD HH:MM:SS)
|
||||||
{{timestamp}} - Unix timestamp
|
{{timestamp}} - Unix timestamp (seconds)
|
||||||
{{year}} - Current year (YYYY)
|
{{year}} - Current year (YYYY)
|
||||||
{{month}} - Current month (MM)
|
{{month}} - Current month (MM)
|
||||||
{{day}} - Current day (DD)
|
{{day}} - Current day (DD)
|
||||||
{{title}} - Note name without extension
|
{{title}} - Note name without extension
|
||||||
{{folder}} - Parent folder name
|
{{folder}} - Parent folder name
|
||||||
|
|
||||||
|
Custom date/time formats (strftime escape hatch):
|
||||||
|
{{date:FMT}}, {{time:FMT}}, {{datetime:FMT}}
|
||||||
|
|
||||||
|
Any of the three date/time placeholders above also accepts an
|
||||||
|
optional ":FMT" suffix where FMT is a Python strftime() format
|
||||||
|
string. Pick the prefix whose default format covers the same
|
||||||
|
components you want to format. Examples:
|
||||||
|
|
||||||
|
{{datetime:%Y%m%d%H%M%S}} -> 20260506154200 (filename-safe stamp)
|
||||||
|
{{date:%d/%m/%Y}} -> 06/05/2026 (European date)
|
||||||
|
{{date:%A}} -> Wednesday (full weekday name)
|
||||||
|
{{time:%H%M%S}} -> 154200 (compact time)
|
||||||
|
{{date:%V}} -> 19 (ISO week number)
|
||||||
|
|
||||||
|
Invalid format strings are left in the output unchanged so a typo
|
||||||
|
is visible rather than silently swallowed.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
content: Template content with placeholders
|
content: Template content with placeholders
|
||||||
note_path: Path of the note being created
|
note_path: Path of the note being created
|
||||||
|
|
@ -989,6 +1013,15 @@ def apply_template_placeholders(content: str, note_path: str) -> str:
|
||||||
now = datetime.now()
|
now = datetime.now()
|
||||||
note = Path(note_path)
|
note = Path(note_path)
|
||||||
|
|
||||||
|
def _strftime_sub(match: 're.Match[str]') -> str:
|
||||||
|
fmt = match.group(2)
|
||||||
|
try:
|
||||||
|
return now.strftime(fmt)
|
||||||
|
except (ValueError, TypeError):
|
||||||
|
return match.group(0)
|
||||||
|
|
||||||
|
content = _STRFTIME_PLACEHOLDER_RE.sub(_strftime_sub, content)
|
||||||
|
|
||||||
replacements = {
|
replacements = {
|
||||||
'{{date}}': now.strftime('%Y-%m-%d'),
|
'{{date}}': now.strftime('%Y-%m-%d'),
|
||||||
'{{time}}': now.strftime('%H:%M:%S'),
|
'{{time}}': now.strftime('%H:%M:%S'),
|
||||||
|
|
|
||||||
|
|
@ -287,6 +287,7 @@ Create notes from reusable templates with dynamic placeholder replacement.
|
||||||
- `{{day}}` - Current day (DD)
|
- `{{day}}` - Current day (DD)
|
||||||
- `{{title}}` - Note name (without extension)
|
- `{{title}}` - Note name (without extension)
|
||||||
- `{{folder}}` - Parent folder name
|
- `{{folder}}` - Parent folder name
|
||||||
|
- `{{date:FORMAT}}` / `{{time:FORMAT}}` / `{{datetime:FORMAT}}` - Custom format using any Python `strftime()` string, e.g. `{{datetime:%Y%m%d%H%M%S}}` → `20251126143045`. See [Templates](TEMPLATES.md#custom-datetime-formats) for the full recipe list.
|
||||||
|
|
||||||
### Example Template
|
### Example Template
|
||||||
```markdown
|
```markdown
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,39 @@ Templates support dynamic placeholders that are replaced when you create a note:
|
||||||
| `{{title}}` | Note name (without .md) | `Weekly Meeting` |
|
| `{{title}}` | Note name (without .md) | `Weekly Meeting` |
|
||||||
| `{{folder}}` | Parent folder name | `Projects` |
|
| `{{folder}}` | Parent folder name | `Projects` |
|
||||||
|
|
||||||
|
### Custom date/time formats
|
||||||
|
|
||||||
|
Need a different format than the defaults above? Any of the three
|
||||||
|
date/time placeholders — `{{date}}`, `{{time}}`, `{{datetime}}` — accepts
|
||||||
|
an optional `:FORMAT` suffix to override its default format. `FORMAT` is
|
||||||
|
any [Python `strftime()` format string](https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes),
|
||||||
|
so anything `strftime` can do, your template can do.
|
||||||
|
|
||||||
|
> **One rule to remember:** pick the prefix whose default already covers
|
||||||
|
> the components you want to format. Use `{{date:…}}` for date-only
|
||||||
|
> formats, `{{time:…}}` for time-only formats, and `{{datetime:…}}` when
|
||||||
|
> you need both.
|
||||||
|
|
||||||
|
#### Common recipes
|
||||||
|
|
||||||
|
| Template | Result | Use case |
|
||||||
|
|---|---|---|
|
||||||
|
| `{{date:%Y%m%d}}` | `20251126` | Date stamp for filenames |
|
||||||
|
| `{{time:%H%M%S}}` | `143045` | Time stamp for filenames |
|
||||||
|
| `{{datetime:%Y%m%d%H%M%S}}` | `20251126143045` | Sortable, filename-safe full stamp |
|
||||||
|
| `{{datetime:%Y%m%dT%H%M%S}}` | `20251126T143045` | ISO-8601 basic, no separators |
|
||||||
|
| `{{datetime:%Y-%m-%dT%H:%M:%S}}` | `2025-11-26T14:30:45` | ISO-8601 extended |
|
||||||
|
| `{{date:%d/%m/%Y}}` | `26/11/2025` | European-style date |
|
||||||
|
| `{{date:%m/%d/%Y}}` | `11/26/2025` | US-style date |
|
||||||
|
| `{{date:%A}}` | `Wednesday` | Full weekday name |
|
||||||
|
| `{{date:%a}}` | `Wed` | Short weekday name |
|
||||||
|
| `{{date:%B}}` | `November` | Full month name |
|
||||||
|
| `{{date:%V}}` | `48` | ISO week number |
|
||||||
|
| `{{date:%j}}` | `330` | Day of year (1–366) |
|
||||||
|
|
||||||
|
> Invalid format strings (typos) are left in the output unchanged so the
|
||||||
|
> mistake is visible rather than silently swallowed.
|
||||||
|
|
||||||
### Example Template
|
### Example Template
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue