Last active
April 24, 2026 17:57
-
-
Save eliduke/94dad4a86e6e64e50d5fa3b214b726d9 to your computer and use it in GitHub Desktop.
Day One JSON to Markdown Converter Script
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| require 'json' | |
| require 'date' | |
| require 'fileutils' | |
| require 'timezone' | |
| # Load specific Day One json data file | |
| json_data = JSON.load_file('Media.json') | |
| # Existing directory where to put everything | |
| export_dir = 'Media' | |
| # Loop through all entries | |
| json_data['entries'].each_with_index do |post, index| | |
| # Create directory for this post where all files will go | |
| post_dir = FileUtils.mkdir "#{export_dir}/#{index.to_s.rjust(3, "0")}-#{post['uuid']}" | |
| # Create internal media directory for all photos and videos related to this post | |
| media_dir = FileUtils.mkdir "#{post_dir.first}/media" | |
| # Create json file of the raw 'entry' for posterity / backup / cya | |
| File.open("#{post_dir.first}/post.json", "wb") do |file| | |
| file.write(JSON.pretty_generate(post)) | |
| end | |
| # Loop through all photos for this post, copy and then rename with added file order | |
| if post['photos'] | |
| post['photos'].each do |photo| | |
| file_name = "#{photo['md5']}.#{photo['type']}" | |
| file_order = photo['orderInEntry'].to_s.rjust(2, "0") | |
| FileUtils.copy_file "photos/#{file_name}", "#{media_dir.first}/#{file_order}-#{file_name}" | |
| end | |
| end | |
| # Loop through all videos for this post, copy and then rename with added file order | |
| if post['videos'] | |
| post['videos'].each do |video| | |
| file_name = "#{video['md5']}.#{video['type']}" | |
| file_order = video['orderInEntry'].to_s.rjust(2, "0") | |
| FileUtils.copy_file "videos/#{file_name}", "#{media_dir.first}/#{file_order}-#{file_name}" | |
| end | |
| end | |
| # Set title, body, and timezone | |
| title, body = JSON.parse(post['richText'])['contents'][0,2] | |
| timezone = Timezone[post['timeZone']] | |
| # Set location info | |
| if post['location'] | |
| location = "#{post['location']['placeName']}, #{post['location']['localityName']}, #{post['location']['administrativeArea']}" | |
| end | |
| # Set weather and moon info | |
| if post['weather'] | |
| temp_in_f = ((post['weather']['temperatureCelsius'] * 1.8) + 32).round | |
| conditions = post['weather']['conditionsDescription'] | |
| moon_phase = post['weather']['moonPhaseCode'].split("-").map(&:capitalize).join(" ") | |
| weather_and_moon = "#{temp_in_f}°F #{conditions} with a #{moon_phase} Moon" | |
| end | |
| # Set list of markdown image/video tags for all media in this post | |
| media_files = Dir["#{media_dir.first}/*"] | |
| media_list = "" | |
| media_files.each do |media| | |
| media_list += ".last})\n\n" | |
| end | |
| # Create markdown file | |
| File.open("#{post_dir.first}/post.md", "wb") do |file| | |
| file.write(<<~EOS | |
| # #{title['text']} | |
| #{body['text']} | |
| #{timezone.time_with_offset(DateTime.parse(post['creationDate']))} | |
| #{location} | |
| #{weather_and_moon} | |
| #{media_list} | |
| EOS | |
| ) | |
| end | |
| end |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is a pretty rough and tumble version that I whipped up in a couple hours, but it works pretty good!
The folder/file structure that it generates looks like this...
And each post's markdown file looks like this...
Suuuuper simple, but much better than the default markdown export.