Skip to content

Instantly share code, notes, and snippets.

@Dog
Last active May 4, 2024 05:48
Show Gist options
  • Save Dog/272225a5b22a393d2088 to your computer and use it in GitHub Desktop.
Save Dog/272225a5b22a393d2088 to your computer and use it in GitHub Desktop.
Converting between Javascript date and Python datetime with bson
from bson.tz_util import utc
from datetime import datetime, timedelta
# This file is to impliment date related helper functions
#
# This is mainly needed because bson uses the javascript date class.
# The javascript Date() class represents timestamps in milliseconds.
# For some documentation on how Bson, Json, and Date work together, refer to:
# http://blog.mongohq.com/from-json-to-bson-and-back/
#
# The python datetime class represents timestamps in seconds.
#
# Furthermore, the python bson class uses its own time zone.
# What this means is that uses datetime.utcfromtimestamp alone is not enough.
# This is because utcfromtimestamp will represent the time zone as None.
# You also can't create your own UTC class, because the datetime comparator
# just checks that the time zone object is of the same ID.
#
# You must use datetime.fromtimestamp(<timestamp>, <tz>)
# Where <timestamp> is the converted timestamp, and <tz> is bson.tz_util.utc
# Precondition: timestamp represented in milliseconds
# timestamp could be either a string or integer
# Returns: DateTime object representing the timestamp given
#
# Possible ToDo: Allow an optional time zone parameter
def bsonToDateTime(timestamp):
# Make sure we are dealing with an integer. If not convert it.
timestamp = int(timestamp)
# Save the milliseconds so they aren't lost in conversion
# due to datetime.fromtimestamp only being as precise as seconds
milliseconds = timestamp % 1000
timestampInSeconds = timestamp / 1000
time = datetime.fromtimestamp(timestampInSeconds, utc)
# convert our milliseconds to microseconds so we can store it in our
# new datetime object to the correct precision
time = time + timedelta(0, 0, 0, milliseconds)
return time
# Precondition: timestamp represented in milliseconds
# timestamp could be either a string or integer
# Returns: DateTime object representing the timestamp given
def dateTimeToBson(dateTimeObject):
# Find the time delta since the epoch
epoch = dateTimeEpoch()
delta = dateTimeObject - epoch
# 60 seconds 60 minutes 24 hours 86400 seconds
# ---------- * ---------- * ---------- = --------------
# 1 minutes 1 hour 1 day 1 day
secondsInDay = 86400
deltaDaysInSeconds = delta.days * secondsInDay
deltaSeconds = delta.seconds
totalSeconds = deltaDaysInSeconds + deltaSeconds
# 1000 milliseconds
# -----------------
# 1 second
totalSecondsToMilliseconds = totalSeconds * 1000
# 1000 microseconds
# -----------------
# 1 millisecond
deltaMilliseconds = delta.microseconds/1000
totalMilliseconds = totalSecondsToMilliseconds + deltaMilliseconds
return totalMilliseconds
def dateTimeEpoch():
return datetime.fromtimestamp(0, utc)
def now():
currentDateTime = datetime.utcnow()
# Use division to round down to correct precision
# Use multiplication to replace the lost zeros
millisecondsRoundedDown = currentDateTime.microsecond/1000*1000
return currentDateTime.replace(tzinfo=utc, microsecond=millisecondsRoundedDown)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment