Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Keeping microsecond precision when passing datetime between django and javascript

It seems django, or the sqlite database, is storing datetimes with microsecond precision. However when passing a time to javascript the Date object only supports milliseconds:

var stringFromDjango = "2015-08-01 01:24:58.520124+10:00";
var time = new Date(stringFromDjango);
$('#time_field').val(time.toISOString()); //"2015-07-31T15:24:58.520Z"

Note the 58.520124 is now 58.520.

This becomes an issue when, for example, I want to create a queryset for all objects with a datetime less than or equal to the time of an existing object (i.e. MyModel.objects.filter(time__lte=javascript_datetime)). By truncating the microseconds the object no longer appears in the list as the time is not equal.

How can I work around this? Is there a datetime javascript object that supports microsecond accuracy? Can I truncate times in the database to milliseconds (I'm pretty much using auto_now_add everywhere) or ask that the query be performed with reduced accuracy?

like image 320
jozxyqk Avatar asked Nov 10 '22 04:11

jozxyqk


1 Answers

How can I work around this?

TL;DR: Store less precision, either by:

  • Coaxing your DB platform to store only miliseconds and discard any additional precision (difficult on SQLite, I think)
  • Only ever inserting values with the precision you want (difficult to ensure you've covered all cases)

Is there a datetime javascript object that supports microsecond accuracy?

If you encode your dates as Strings or Numbers you can add however much accuracy you'd like. There are other options (some discussed in this thread). Unless you actually want this accuracy though, it's probably not the best approach.

Can I truncate times in the database to milliseconds..

Yes, but because you're on SQLite it's a bit weird. SQLite doesn't really have dates; you're actually storing the values in either a text, real or integer field. These underlying storage classes dictate the precision and range of the values you can store. There's a decent write up of the differences here.

You could, for example, change your underlying storage class to integer. This would truncate dates stored in that field to a precision of 1 second. When performing your queries from JS, you could likewise truncate your dates using the Date.prototype.setMilliseconds() function. Eg..

MyModel.objects.filter(time__lte = javascript_datetime.setMilliseconds(0))

A more feature complete DB platform would handle it better. For example in PostgreSQL you can specify the precision stored more exactly. This will add a timestamp column with precision down to miliseconds (matching that of Javascript)..

alter table "my_table" add "my_timestamp" timestamp (3) with time zone

MySQL will let you do the same thing.

.. or ask that the query be performed with reduced accuracy?

Yeah but this is usually the wrong approach.

If the criteria you're filtering by is to precise then you're ok; you can truncate the value then filter (like in the ..setMilliseconds() example above). But if the values in the DB you're checking against are too precise you're going to have a Bad Time.

You could write a query such that the stored values are formatted or truncated to reduce their precision before being compared to your criteria but that operation is going to need to be performed for every value stored. This could be millions of values. What's more, because you're generating the values dynamically, you've just circumvented any indexes created against the stored values.

like image 160
Molomby Avatar answered Nov 14 '22 21:11

Molomby