dates are now stored in UTC and displayed in local time

This commit is contained in:
azivner 2017-09-30 22:35:13 -04:00
parent 569f7a392d
commit d0cc5f4a5f
8 changed files with 31 additions and 11 deletions

5
TODO
View File

@ -1,7 +1,8 @@
- conflict detection
- note title and content changes are not in audit_log table
- deleting cloned nodes ends with 500 (probably only on folders) - deleting cloned nodes ends with 500 (probably only on folders)
- what links here - what links here
- recent changes - link to note should lead to the revision - recent changes - link to note should lead to the revision
- db upgrade / migration - db upgrade / migration
- dates should be stored in UTC to work correctly with time zones - dates should be stored in UTC to work correctly with time zones
- we should also record timezone info so that we display the date correctly with respect to the local date at the time of recording it
- modularize frontend
- unify handling of global variables

View File

@ -12,6 +12,7 @@ from sql import delete
from sql import execute, insert, commit from sql import execute, insert, commit
from sql import getResults, getSingleResult, getOption, addAudit, deleteRecentAudits from sql import getResults, getSingleResult, getOption, addAudit, deleteRecentAudits
import utils
import audit_category import audit_category
notes_api = Blueprint('notes_api', __name__) notes_api = Blueprint('notes_api', __name__)
@ -44,7 +45,7 @@ def updateNote(note_id):
note = request.get_json(force=True) note = request.get_json(force=True)
now = math.floor(time.time()) now = utils.nowTimestamp()
history_snapshot_time_interval = float(getOption('history_snapshot_time_interval')) history_snapshot_time_interval = float(getOption('history_snapshot_time_interval'))
@ -154,7 +155,7 @@ def createChild(parent_note_id):
addAudit(audit_category.CREATE_NOTE, request, noteId) addAudit(audit_category.CREATE_NOTE, request, noteId)
now = math.floor(time.time()) now = utils.nowTimestamp()
insert("notes", { insert("notes", {
'note_id': noteId, 'note_id': noteId,

View File

@ -4,6 +4,8 @@ import sqlite3
import math import math
import time import time
import utils
conn = None conn = None
def dict_factory(cursor, row): def dict_factory(cursor, row):
@ -36,7 +38,7 @@ def getOption(name):
return getSingleResult("SELECT opt_value FROM options WHERE opt_name = ?", [name])['opt_value'] return getSingleResult("SELECT opt_value FROM options WHERE opt_name = ?", [name])['opt_value']
def addAudit(category, request = None, note_id = None, change_from = None, change_to = None, comment = None): def addAudit(category, request = None, note_id = None, change_from = None, change_to = None, comment = None):
now = math.floor(time.time()) now = utils.nowTimestamp()
browser_id = None browser_id = None
@ -49,7 +51,7 @@ def addAudit(category, request = None, note_id = None, change_from = None, chang
def deleteRecentAudits(category, request, note_id): def deleteRecentAudits(category, request, note_id):
browser_id = request.headers['x-browser-id'] browser_id = request.headers['x-browser-id']
delete_cutoff = math.floor(time.time()) - 10 * 60; delete_cutoff = utils.nowTimestamp() - 10 * 60;
execute("DELETE FROM audit_log WHERE category = ? AND browser_id = ? AND note_id = ? AND date_modified > ?", execute("DELETE FROM audit_log WHERE category = ? AND browser_id = ? AND note_id = ? AND date_modified > ?",
[category, browser_id, note_id, delete_cutoff]) [category, browser_id, note_id, delete_cutoff])

View File

@ -7,6 +7,7 @@ from flask import Blueprint, jsonify
from flask_login import login_required from flask_login import login_required
from sql import getResults, getSingleResult, getOption from sql import getResults, getSingleResult, getOption
import utils
tree_api = Blueprint('tree_api', __name__) tree_api = Blueprint('tree_api', __name__)
@ -50,6 +51,6 @@ def getTree():
retObject['encrypted_data_key'] = getOption('encrypted_data_key') retObject['encrypted_data_key'] = getOption('encrypted_data_key')
retObject['encryption_session_timeout'] = getOption('encryption_session_timeout') retObject['encryption_session_timeout'] = getOption('encryption_session_timeout')
retObject['browser_id'] = base64.b64encode(os.urandom(8)) retObject['browser_id'] = base64.b64encode(os.urandom(8))
retObject['full_load_time'] = math.floor(time.time()) retObject['full_load_time'] = utils.nowTimestamp()
return jsonify(retObject) return jsonify(retObject)

5
src/utils.py Normal file
View File

@ -0,0 +1,5 @@
from datetime import datetime
import time
def nowTimestamp():
return time.mktime(datetime.utcnow().timetuple())

View File

@ -15,6 +15,16 @@ $(document).bind('keydown', 'alt+s', function() {
$("input[name=search]").focus(); $("input[name=search]").focus();
}); });
function getDateFromTS(timestamp) {
// Date accepts number of milliseconds since epoch so UTC timestamp works without any extra handling
// see https://stackoverflow.com/questions/4631928/convert-utc-epoch-to-local-date-with-javascript
const utcDate = new Date(timestamp * 1000);
const localDate = new Date(utcDate.getTime() - utcDate.getTimezoneOffset() * 60 * 1000);
return localDate;
}
function formatTime(date) { function formatTime(date) {
return (date.getHours() <= 9 ? "0" : "") + date.getHours() + ":" + (date.getMinutes() <= 9 ? "0" : "") + date.getMinutes(); return (date.getHours() <= 9 ? "0" : "") + date.getHours() + ":" + (date.getMinutes() <= 9 ? "0" : "") + date.getMinutes();
} }

View File

@ -17,7 +17,7 @@ $(document).bind('keydown', 'alt+h', function() {
globalHistoryItems = result; globalHistoryItems = result;
for (const row of result) { for (const row of result) {
const dateModified = new Date(row.date_modified * 1000); const dateModified = getDateFromTS(row.date_modified);
$("#noteHistoryList").append($('<option>', { $("#noteHistoryList").append($('<option>', {
value: row.id, value: row.id,

View File

@ -21,7 +21,7 @@ $(document).bind('keydown', 'alt+r', function() {
} }
} }
const dateModified = new Date(row.date_modified * 1000); const dateModified = getDateFromTS(row.date_modified);
const formattedDate = formatDate(dateModified); const formattedDate = formatDate(dateModified);
if (!groupedByDate[formattedDate]) { if (!groupedByDate[formattedDate]) {
@ -41,7 +41,7 @@ $(document).bind('keydown', 'alt+r', function() {
const dayEl = $('<div>').append($('<b>').html(formattedDay)).append(changesListEl); const dayEl = $('<div>').append($('<b>').html(formattedDay)).append(changesListEl);
for (const dayChanges of groupedByDate[formattedDay]) { for (const dayChanges of groupedByDate[formattedDay]) {
const formattedTime = formatTime(new Date(dayChanges.date_modified * 1000)); const formattedTime = formatTime(getDateFromTS(dayChanges.date_modified));
const noteLink = $("<a>", { const noteLink = $("<a>", {
href: 'app#' + dayChanges.note_id, href: 'app#' + dayChanges.note_id,