Obsidian import: More intelligent time behaviour
Some checks failed
Test Python / Test (push) Failing after 32s
Some checks failed
Test Python / Test (push) Failing after 32s
This commit is contained in:
parent
a64cbc6186
commit
c8c142bd1b
|
@ -119,8 +119,9 @@ def import_watched_series_csv(vault: ObsidianVault, rows: Rows) -> int:
|
|||
sample.single_label_with_category('episode.index'),
|
||||
sample.single_label_with_category('episode.name'),
|
||||
)
|
||||
return Event(sample.start_at.time(),
|
||||
sample.end_at.time(),
|
||||
expected_tz = datetime.timezone(datetime.timedelta(hours=2)) # TODO: Determine this in a more intelligent manner
|
||||
return Event(sample.start_at.astimezone(expected_tz).replace(second=0,microsecond=0).time(),
|
||||
sample.end_at.astimezone(expected_tz).replace(second=0,microsecond=0).time(),
|
||||
verb,
|
||||
sample.single_label_with_category('series.name'),
|
||||
comment,
|
||||
|
@ -162,6 +163,5 @@ def import_data(obsidian_path: Path, dry_run=True):
|
|||
data_path = Path('output/show_episodes_watched.csv')
|
||||
rows = load_csv_file(data_path)
|
||||
logger.info('Loaded CSV with %d lines', len(rows))
|
||||
rows = rows[:7]
|
||||
num_updated = import_watched_series_csv(vault, rows)
|
||||
logger.info('Updated %d files', num_updated)
|
||||
|
|
|
@ -210,25 +210,43 @@ def format_event_string(event: Event) -> str:
|
|||
):
|
||||
return event.comment
|
||||
|
||||
return f'{event.start_time:%H:%M} | {event.verb} [[{event.subject}]]. {event.comment}'.strip()
|
||||
buf = []
|
||||
buf.append(f'{event.start_time:%H:%M}')
|
||||
if event.end_time and event.end_time != event.start_time:
|
||||
buf.append(f'-{event.end_time:%H:%M}')
|
||||
buf.append(' | ')
|
||||
buf.append(event.verb)
|
||||
buf.append(' [[')
|
||||
buf.append(event.subject)
|
||||
buf.append(']]. ')
|
||||
buf.append(event.comment.strip())
|
||||
|
||||
return ''.join(buf)
|
||||
|
||||
|
||||
RE_TIME = r'(\d\d:\d\d(?::\d\d(?:\.\d+?))?)'
|
||||
RE_VERB = r'(\w+(?:ed|te))'
|
||||
RE_LINK_MD = r'\[([^\]]*)\]\(?:[^)]*\)'
|
||||
RE_LINK_WIKI = r'\[\[([^\]]*)\]\]'
|
||||
|
||||
RE_TIME_FORMAT = RE_TIME + r'(?:\s*\-\s*' + RE_TIME + r')?'
|
||||
|
||||
|
||||
def parse_event_string(event_str: str) -> Event:
|
||||
if m := re.match(
|
||||
r'^\s*' + RE_TIME + r'[ :\|-]*(\w+ed)\s+\[([^\]]*)\]\([^)]*\)\.?\s*(.*)$',
|
||||
r'^\s*' + RE_TIME_FORMAT + r'[ :\|-]*'+RE_VERB+r'\s+'+RE_LINK_MD+r'\.?\s*(.*)$',
|
||||
event_str,
|
||||
):
|
||||
start = datetime.time.fromisoformat(m.group(1))
|
||||
return Event(start, start, m.group(2), m.group(3), m.group(4))
|
||||
end = datetime.time.fromisoformat(m.group(2)) if m.group(2) else start
|
||||
return Event(start, end, m.group(3), m.group(4), m.group(5))
|
||||
if m := re.match(
|
||||
r'^\s*' + RE_TIME + '[ :\|-]*(\w+ed)\s+\[\[([^\]]*)\]\]\.?\s*(.*)$',
|
||||
r'^\s*' + RE_TIME_FORMAT + r'[ :\|-]*'+RE_VERB+r'\s+'+RE_LINK_WIKI+r'\.?\s*(.*)$',
|
||||
event_str,
|
||||
):
|
||||
start = datetime.time.fromisoformat(m.group(1))
|
||||
return Event(start, start, m.group(2), m.group(3), m.group(4))
|
||||
end = datetime.time.fromisoformat(m.group(2)) if m.group(2) else start
|
||||
return Event(start, end, m.group(3), m.group(4), m.group(5))
|
||||
logger.info('Could not parse format: %s', event_str)
|
||||
return Event(None, None, None, None, event_str)
|
||||
|
||||
|
|
|
@ -23,6 +23,10 @@ class ActivitySample:
|
|||
start_at: datetime.datetime | None
|
||||
end_at: datetime.datetime | None
|
||||
|
||||
def __post_init__(self):
|
||||
if self.start_at and self.end_at:
|
||||
assert self.start_at <= self.end_at
|
||||
|
||||
def single_label_with_category(self, category: str) -> str:
|
||||
for label in self.labels:
|
||||
if label.category == category:
|
||||
|
@ -35,6 +39,11 @@ class RealizedActivitySample(ActivitySample):
|
|||
start_at: datetime.datetime
|
||||
end_at: datetime.datetime
|
||||
|
||||
def __post_init__(self):
|
||||
assert self.start_at is not None
|
||||
assert self.end_at is not None
|
||||
assert self.start_at <= self.end_at
|
||||
|
||||
|
||||
def heuristically_realize_samples(
|
||||
samples: list[ActivitySample],
|
||||
|
@ -45,6 +54,8 @@ def heuristically_realize_samples(
|
|||
* No samples overlap.
|
||||
"""
|
||||
|
||||
samples.sort(key = lambda x: x.end_at)
|
||||
|
||||
previous_sample_end = None
|
||||
for sample in samples:
|
||||
end_at = sample.end_at
|
||||
|
|
18
test/test_obsidian_format.py
Normal file
18
test/test_obsidian_format.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
import datetime
|
||||
import pytest
|
||||
|
||||
from obsidian_import import obsidian
|
||||
|
||||
|
||||
EXAMPLES = [
|
||||
obsidian.Event(datetime.time(12, 0, 0), datetime.time(12, 0, 0), "Ate",
|
||||
"Lunch", "instantly"),
|
||||
obsidian.Event(datetime.time(20, 0, 0), datetime.time(22, 0, 0),
|
||||
"Watched", "Tom and Jerry", "on the *Television*"),
|
||||
obsidian.Event(None, None, None, None, "Took a walk"),
|
||||
]
|
||||
|
||||
@pytest.mark.parametrize("event", EXAMPLES)
|
||||
def test_format_preserves_information(event: obsidian.Event):
|
||||
formatted = obsidian.format_event_string(event)
|
||||
assert obsidian.parse_event_string(formatted) == event
|
Loading…
Reference in New Issue
Block a user