-module(ts_json). -export([encode_record/1, record_to_ejson/1, ejson_to_record/2]). -include("ts_db_records.hrl"). encode_record(Record) -> lists:flatten(json:encode(record_to_ejson(Record))). record_to_ejson(Record=#ts_user{}) -> {struct, [ {username, atom_to_list(Record#ts_user.username)}, {name, Record#ts_user.name}, {email, Record#ts_user.email}, {join_date, encode_datetime(Record#ts_user.join_date)}]}; record_to_ejson(Record=#ts_timeline{}) -> % pull out the username and timeline id {Username, TimelineId} = Record#ts_timeline.ref, % create the EJSON struct {struct, [ {username, atom_to_list(Username)}, {timeline_id, atom_to_list(TimelineId)}, {created, encode_datetime(Record#ts_timeline.created)}, {description, Record#ts_timeline.desc}]}; record_to_ejson(Record=#ts_entry{}) -> % pull out the username, timeline id, and entry id {Username, TimelineId, EntryId} = Record#ts_entry.ref, % convert the timestamp to a date-time DateTime = calendar:gregorian_seconds_to_datetime(Record#ts_entry.timestamp), % create the EJSON struct {struct, [ {username, atom_to_list(Username)}, {timeline_id, atom_to_list(TimelineId)}, {entry_id, EntryId}, {timestamp, encode_datetime(DateTime)}, {mark, Record#ts_entry.mark}, {notes, Record#ts_entry.notes}]}. encode_datetime({{Year, Month, Day}, {Hour, Minute, Second}}) -> lists:flatten(io_lib:format("~4.10.0B-~2.10.0B-~2.10.0BT~2.10.0B:~2.10.0B:~2.10.0B~3.10.0BZ", [Year, Month, Day, Hour, Minute, Second, 000])). ejson_to_record(_Empty=#ts_timeline{}, EJSON) -> {struct, Fields} = EJSON, #ts_timeline{ ref = {undefined, undefined}, created = decode_datetime(element(2, lists:keyfind(created, 1, Fields))), desc = element(2, lists:keyfind(description, 1, Fields))}; ejson_to_record(_Empty=#ts_entry{}, EJSON) -> {struct, Fields} = EJSON, #ts_entry{ ref = {undefined, undefined, undefined}, timestamp = calendar:datetime_to_gregorian_seconds(decode_datetime( element(2, lists:keyfind(timestamp, 1, Fields)))), mark = element(2, lists:keyfind(mark, 1, Fields)), notes = element(2, lists:keyfind(notes, 1, Fields))}. decode_datetime(DateTimeString) -> % TODO: catch badmatch and badarg on whole function [DateString, TimeString] = re:split(DateTimeString, "[TZ]", [{return, list}, trim]), [YearString, MonthString, DayString] = re:split(DateString, "-", [{return, list}]), [HourString, MinuteString, SecondString] = case re:split(TimeString, "[:\\.]", [{return, list}]) of [HS, MS, SS, _MSS] -> [HS, MS, SS]; [HS, MS, SS] -> [HS, MS, SS] end, Date = {list_to_integer(YearString), list_to_integer(MonthString), list_to_integer(DayString)}, Time = {list_to_integer(HourString), list_to_integer(MinuteString), list_to_integer(SecondString)}, {Date, Time}.