Last active
February 6, 2016 22:16
-
-
Save apiarian/0f8e0970af52bd03db54 to your computer and use it in GitHub Desktop.
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
# export_dayone_entries.py | |
# Aleksandr Pasechnik | |
# | |
# This script goes through the Day One journal and exports each of the entries | |
# to a new markdown file in the `exportdir` directory. The `exportdir` | |
# directory is deleted and recreated each time the script is run, so best set | |
# it to something temporary (a subdirectory on the Desktop, for example). | |
# Photos are copied into the export directory too, with the same basename as | |
# the exported entries. The timestamp, location, weather, and tags are appended | |
# to the end of the file, if they are available. The script also sticks a '#' | |
# at the head of the first line, making that line into an H1 heading. Analogous | |
# to DayOne's "Bold first line" setting. | |
# | |
# NOTE: the `exportdir` is deleted and recreated each time the script is run. | |
# NOTE: this script ignores some of the data available in a full DayOne entry | |
# plist. Adapt to your own needs. | |
import os | |
import plistlib | |
import shutil | |
import pytz | |
import re | |
debug = True; | |
basedir = '~/Library/Mobile Documents/5U8NS4GX82~com~dayoneapp~dayone/Documents/Journal_dayone' | |
basedir = os.path.expanduser(basedir) | |
entriesdir = os.path.join(basedir, 'entries') | |
photosdir = os.path.join(basedir, 'photos') | |
exportdir = '~/Desktop/journal_export' | |
exportdir = os.path.expanduser(exportdir) | |
try: | |
shutil.rmtree(exportdir) | |
except: | |
pass | |
os.mkdir(exportdir) | |
filenames = os.listdir(entriesdir) | |
filenames = [filename for filename in filenames if filename.endswith('.doentry')] | |
entries = [] | |
for filename in filenames: | |
filename = os.path.join(entriesdir, filename) | |
entry = plistlib.readPlist(filename) | |
photofilename = os.path.join(photosdir, entry['UUID']+'.jpg') | |
if os.path.exists(photofilename): | |
entry['__PHOTO_FILENAME__'] = photofilename | |
entries.append(entry) | |
utctimezone = pytz.utc | |
def degrees_to_dmsd(float_degrees): | |
float_degrees = abs(float_degrees) | |
degrees = int(float_degrees) | |
minutes_decimal = abs(float_degrees - degrees) * 60 | |
minutes = int(minutes_decimal) | |
seconds_decimal = (minutes_decimal - minutes) * 60 | |
seconds = int(seconds_decimal) | |
seconds_fraction = int((seconds_decimal - seconds) * 10) | |
return (degrees, minutes, seconds, seconds_fraction) | |
unique_tags = [] | |
for entry in entries: | |
creationdate = entry['Creation Date'] | |
timezone = pytz.timezone(entry['Time Zone']) | |
localtimestamp = utctimezone.localize(creationdate).astimezone(timezone) | |
yearpart = localtimestamp.strftime('%Y') | |
try: | |
os.mkdir(os.path.join(exportdir,yearpart)) | |
except: | |
pass | |
monthpart = localtimestamp.strftime('%m - %B') | |
try: | |
os.mkdir(os.path.join(exportdir,yearpart,monthpart)) | |
except: | |
pass | |
entry['__LOCAL_TIMESTAMP__'] = localtimestamp | |
filenamebase = localtimestamp.strftime('%Y-%m-%d %H-%M-%S %a'); | |
f = open(os.path.join(exportdir, yearpart, monthpart, filenamebase+'.md'),'w') | |
f.write('# '); f.write(entry['Entry Text'].strip()) | |
if '__PHOTO_FILENAME__' in entry.keys(): | |
photofilename = filenamebase.replace(' ', '-')+'.jpg' | |
f.write('\n\n'.format(photofilename)) | |
shutil.copy( | |
entry['__PHOTO_FILENAME__'], | |
os.path.join(exportdir, yearpart, monthpart, photofilename) | |
) | |
f.write('\n\n---\n\n') | |
zero_padded_day = localtimestamp.strftime('%d') | |
unpadded_day = re.sub(r'^[0]?(.*)',r'\1',zero_padded_day) | |
f.write( | |
localtimestamp.strftime( | |
'**Timestamp:** %A, %B {}, %Y at %H:%M:%S {}\n\n'.format(unpadded_day,entry['Time Zone'].replace('_',' ')) | |
) | |
) | |
if 'Location' in entry.keys(): | |
location = entry['Location'] | |
location_parts = [] | |
for key in ['Place Name', 'Locality', 'Administrative Area', 'Country']: | |
try: | |
location_parts.append(location[key]) | |
except: | |
pass | |
lat_lon = '' | |
try: | |
lat = float(location['Latitude']) | |
lon = float(location['Longitude']) | |
lat_unit = 'N' if lat >= 0 else 'S' | |
lon_unit = 'E' if lon >= 0 else 'W' | |
lat_dms = "{0[0]:02}˚{0[1]:02}'{0[2]:02}.{0[3]:02}\"".format(degrees_to_dmsd(lat)) | |
lon_dms = "{0[0]:02}˚{0[1]:02}'{0[2]:02}.{0[3]:02}\"".format(degrees_to_dmsd(lon)) | |
lat_lon = ' ({} {}, {} {})'.format(lat_dms, lat_unit, lon_dms, lon_unit) | |
except: | |
pass | |
f.write('**Location:** {}{}\n\n'.format( | |
', '.join(location_parts), | |
lat_lon, | |
)) | |
processed_keys = [ | |
'Place Name', | |
'Locality', | |
'Administrative Area', | |
'Country', | |
'Latitude', | |
'Longitude', | |
'Foursquare ID', | |
'Region', | |
'State', | |
'FourSquareLocation' | |
] | |
missed_keys = [key for key in location.keys() if key not in processed_keys] | |
if missed_keys and debug: | |
print('Missed Location Keys: {}'.format(missed_keys)) | |
if 'Weather' in entry.keys(): | |
weather = entry['Weather'] | |
f.write('**Weather:** {}, {}˚F ({}˚C)\n\n'.format( | |
weather['Description'], | |
weather['Fahrenheit'], | |
weather['Celsius'], | |
)) | |
processed_keys = [ | |
'Description', | |
'Fahrenheit', | |
'Celsius', | |
'IconName', | |
'Wind Bearing', | |
'Service', | |
'Wind Speed KPH', | |
'Visibility KM', | |
'Relative Humidity', | |
'Pressure MB', | |
'Wind Chill Celsius', | |
'Sunset Date', | |
'Sunrise Date', | |
] | |
missed_keys = [key for key in weather.keys() if key not in processed_keys] | |
if missed_keys and debug: | |
print('Missed Weather Keys: {}'.format(missed_keys)) | |
if 'Tags' in entry.keys() and entry['Tags']: | |
tagstring = ', '.join(entry['Tags']) | |
f.write('**Tags:** {}\n\n'.format(tagstring)) | |
for tag in entry['Tags']: | |
if tag not in unique_tags: | |
unique_tags.append(tag) | |
f.close() | |
processed_keys = [ | |
'Creation Date', | |
'Time Zone', | |
'Entry Text', | |
'__LOCAL_TIMESTAMP__', | |
'__PHOTO_FILENAME__', | |
'Starred', | |
'UUID', | |
'Tags', | |
'Weather', | |
'Location', | |
'Creator', | |
'Music', | |
'Activity', | |
'Step Count', | |
'Ignore Step Count', | |
] | |
missed_keys = [key for key in entry.keys() if key not in processed_keys] | |
if missed_keys and debug: | |
print('Missed keys: {}'.format(missed_keys)) | |
unique_tags.sort() | |
print('Tags:') | |
for tag in unique_tags: | |
print('\t{}'.format(tag)) | |
#import bpython | |
#bpython.embed(locals_ = locals()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment