Skip to content

Enhancement: preserve note modified date when importing from Joplin - #3715

Merged
pbek merged 1 commit into
pbek:mainfrom
MySkeletonHurts:fix/joplin-import-preserve-timestamps
Aug 31, 2026
Merged

Enhancement: preserve note modified date when importing from Joplin#3715
pbek merged 1 commit into
pbek:mainfrom
MySkeletonHurts:fix/joplin-import-preserve-timestamps

Conversation

@MySkeletonHurts

@MySkeletonHurts MySkeletonHurts commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #3672. The Joplin importer currently doesn't try to preserve
a note's real modified date — every imported note's file_last_modified
ends up as "whenever the import happened to write that file", so
Note -> Sort by -> By date (and search, which sorts the same list) can't
reflect a note's actual history after import. For a large imported
collection this mostly reads as random. This PR adds that, written with
Claude Code.

The change is small. importNote() already reads one field out of a note's
Joplin metadata block (parent_id:, for subfolder placement) via a regex
against the same text variable already in scope — this just adds a
second regex for updated_time: (Joplin's ISO-8601-with-milliseconds
timestamp, e.g. 2019-11-15T16:16:34.302Z, which QDateTime::fromString
parses natively via Qt::ISODateWithMs), and applies it to the file with
QFile::setFileTime() as the very last step of the import, after all the
existing storeNoteTextFileToDisk() calls so nothing overwrites it
afterward. One thing worth flagging in review: setFileTime() only takes
effect if the file is open when it's called — easy to miss, since it fails
silently otherwise.

setFileTime() needs Qt 5.10+; the project floor is Qt 5.5, so the whole
block is behind a QT_VERSION_CHECK guard (same pattern already used
elsewhere in this codebase, e.g. linkdialog.cpp) — pre-5.10 Qt5 builds
just skip the correction and keep today's behavior, nothing breaks.

Scoped to modified time only. Creation time seemed worth attempting too at
first, but most POSIX filesystems (Linux included) don't expose a way to
set birth time after the fact via the calls Qt/the OS provide, so it'd be
dead code there — and modified time is what actually drives the sorting
that motivated this.

Validation

Built and ran the enhanced importer's GUI against a synthetic repro export
(attached, 12 notes spanning 1998-2024). Currently, every imported note's
modified date collapses to the moment the import ran; with this change,
each one's file mtime (and the file_last_modified the app sorts by)
matches its real Joplin updated_time, confirmed down to correct
UTC-to-local conversion.

Repro data

Small synthetic Joplin RAW export, no real data — 12 notes, each titled
like Tag [2019-11-14] Doctor visit - lab results, spanning 1998-2024.
The leading tag word is assigned in alphabetical order but in a note order
that's deliberately not chronological, so alphabetical-sort-order and
date-sort-order provably disagree — meaning correct sort order after import
demonstrates the change is reading each note's real date, not just
coincidentally reproducing title-string order. Attached as
repro-timestamps.zip. Import via "Import notes from Joplin"; currently,
Note -> Sort by -> By date comes out scrambled relative to the titles'
dates, and with this change it reads in correct chronological order.

repro-timestamps.zip

Joplin's raw export carries each note's real created_time/updated_time in
its metadata block, but the importer never read it, so every imported
note's file_last_modified ended up as "whenever the import ran" instead
of the note's real history, breaking Note -> Sort by -> By date.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@pbek
pbek merged commit f86c9e6 into pbek:main Aug 31, 2026
39 checks passed
@pbek

pbek commented Aug 31, 2026

Copy link
Copy Markdown
Owner

Thank you!

pbek added a commit that referenced this pull request Aug 31, 2026
Signed-off-by: Patrizio Bekerle <patrizio@bekerle.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants