Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Convert Day One (macOS) Journal.txt to Emacs org-mode diary/journal — https://christiantietze.de/posts/2020/10/export-day-one-journal-to-org-mode/
#!/usr/bin/env ruby
#
# convert_dayone_to_org.rb
# Copyright © 2020 Christian Tietze. All rights reserved. Distributed under the MIT License.
#
# Converts a Day One plain text export (Journal.txt) into org-mode journal format. It does
# - Markdown image conversion from ![](thepath.jpg) to [[thepath.jpg]]
# - Extraction of images from the front of an entry; moves it right after the property drawer.
# - Creation of nested year/month/day date sections (see example below)
#
# TODOs:
# - changing the image directory name during import using an option
# - changing the hash-based image file names to date-time format
#
# Usage:
#
# ./convert_dayone_to_org.rb Journal.txt output.org
#
# Output:
#
# * 2020
# ** 2020-03 March
# *** 2020-03-14 Saturday
# **** Here's a diary entry imported from Day One.
# :PROPERTIES:
# :CREATED: [2020-03-14 Sat 14:33]
# :END_PROPERTIES:
# **** And another one from the same day.
# :PROPERTIES:
# :CREATED: [2020-03-14 Sat 19:12]
# :END_PROPERTIES:
# ** 2020-06 June
# *** 2020-06-22 Monday
# **** Year, month, and day sections are created automatically.
# :PROPERTIES:
# :CREATED: [2020-06-22 Mon 08:06]
# :END_PROPERTIES:
require "date"
input, output, *rest = ARGV
if input.nil?
STDERR.puts "Usage: #{__FILE__} DAYONE_INPUT_PATH ORG_OUTPUT_PATH"
STDERR.puts "Missing input file path"
exit 1
elsif output.nil?
STDERR.puts "Usage: #{__FILE__} DAYONE_INPUT_PATH ORG_OUTPUT_PATH"
STDERR.puts "Missing output file path"
exit 1
end
File.open(output, "w") do |out|
# Cached values to make sub-headings
year = nil
month = nil
day = nil
props = {}
File.readlines(input).each do |line|
if /\A\t(?<key>\w+):\t(?<value>.*+)$/ =~ line
# Collect metadata in `props` dictionary
case key
when "Date"
date = DateTime.parse(value)
props["Created"] = date.strftime("[%Y-%m-%d %a %H:%M]")
# Convert date lines to new entries in org
# Output: "* 2020"
if year != date.year
out.puts "* #{date.year}"
year = date.year
month = nil
end
# Output: "** 2020-03 March"
if month != date.month
out.puts "** #{date.strftime("%Y-%m %B")}"
month = date.month
end
# Output: "*** 2020-03-12 Thursday"
this_day = date.strftime("%Y-%m-%d %A")
if day != this_day
out.puts "*** #{this_day}"
end
else
props[key] = value
end
elsif !props.empty?
# Produce entry title and metadata
if line.strip.empty?
# Skip empty line separator after metadata
else
# Add entry heading, handling leading entry images
cached_image = nil
if /\A!\[]\((?<path>.+)\)(?<rest>.*)$/ =~ line
cached_image = "[[./#{path}]]"
out.puts "**** #{rest}"
else
out.puts "**** #{line}"
end
# Append property drawer
out.puts ":PROPERTIES:"
out.puts(props.map { |key, value| ":" + key.upcase.to_s + ": " + value.to_s }
.join("\n"))
out.puts ":END_PROPERTIES:"
props = {}
if !cached_image.nil?
out.puts ""
out.puts cached_image
end
end
else
line = line.gsub(/!\[\]\((.+)\)/) { "[[./#{$1}]]" }
out.puts line
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.