You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Rapidjson supports ISO8601 format for datetime object in dump. Possible to add support for unix timestamp?
(can be handled with "default" parameter in dump but it is nice to have it built-in).
python
Python 3.5.0 (default, Sep 23 2015, 04:42:00)
[GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.72)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import rapidjson
>>> from datetime import datetime
>>> rapidjson.dumps(datetime.now(), datetime_mode=1)
'"2017-02-22T11:00:28.885223"'
>>>
Python 3.6.0 |Continuum Analytics, Inc.| (default, Dec 23 2016, 12:22:00)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import rapidjson
>>> from datetime import datetime
>>> from calendar import timegm
>>> def encode_datetime(obj):
... if isinstance(obj, datetime):
... return int(timegm(obj.timetuple())) # returns unix timestamp, UTC time
... raise TypeError(repr(obj) + " is not JSON serializable")
...
>>> rapidjson.dumps(datetime.now(), default=encode_datetime)
'1487766521'
>>>
possible to have this built-in?
(ujson is returning unix timestamp by default).
While it'd be quite easy to add another flag for that, the fact that it could work only for serialization makes me somewhat unhappy...
BTW, isn't that equivalent to obj.timestamp()?
obj.timestamp() doesn't return UTC time. Rapidjson is already handling ISO8601 format. I think it would be useful to add support for unix timestamp.
We are trying to switch from ujson to rapidjson and this is the main problem that we are encountering.
yes. we are processing millions of jsons at a time. ujson doesn't support the Decimal objects properly especially when more than 9 precisions are needed.
Python 3.6.0 |Continuum Analytics, Inc.| (default, Dec 23 2016, 12:22:00)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import simplejson
>>> import ujson
>>> import rapidjson
>>> from decimal import Decimal
>>> simplejson.dumps({"c": 173688.15}, use_decimal=True)
'{"c": 173688.15}'
>>> rapidjson.dumps({"c": 173688.15}, use_decimal=True)
'{"c":173688.15}'
>>> ujson.dumps({"c": 173688.15}, double_precision=15)
'{"c":173688.149999999994179}'
>>> a = {"p": Decimal('45.123456789012349').quantize(Decimal('0.000000000000001'))}
>>> simplejson.dumps(a, use_decimal=True)
'{"p": 45.123456789012349}'
>>> rapidjson.dumps(a, use_decimal=True)
'{"p":45.123456789012349}'
>>> ujson.dumps(a, double_precision=15)
'{"p":45.123456789012351}'
>>>
I will try to make some experiment on this, next week. Do you think it would require a "combination" of flags, to be able to obtain either the "floating point" value like standard lib .timestamp() or the "integer" value like you asked above, and of course native/UTC like current DATETIME_MODE?
I think having both flags is good. In our case we need integer (ujson returns integer as well) but to be more precise having the same output as .timestamp() will be useful. For the DATETIME_MODEUTC should be enough.
Not sure about datetime.date and datetime.time.
@lelit, for datetime.date and datetime.time instances, I don't think we need to do anything. They are already formatted. (Also, I don't think anything can be done for datetime.time instances because there isn't enough info to create a unix timestamp from just time).
I think those can be left with their default formatting.
The reason we need formatting options for .timetuple() instance is that it returns an object and not a formatted string.
Yes, I agree that this "timestamp" serialization of datetimes does not apply to dates and times.
What I can't see right now is a way to tell rapidjson that I want datetimes serialized as timestamps and dates as their ISO8601 representation. In other words, currently I can say
but how can I get the first item formatted as a timestamp instead, while treating the second in the same way? Maybe change those DATETIME_XXX constants to be bit flags instead of their current consecutive integer values, so that the last statement would read
That's a good point. Maybe in that case it would be better to format all datetime instances in the same way, for the sake of simplicity and consistency.
@s-alikarimi what do you think?
In this case my datetime object is a UTC time and it needs to return 2017-02-27 10:20:00. timegm() returns 2017-02-27 10:20:00 while timestamp() returns 2017-02-27 15:20:00.
AFAIU, this tells me a different story: the dt value is actually a naïve datetime, that is a value without a timezone, while the latter, dtutc, is clearly a timezone aware datetime, explicitly set to UTC; to compute the timestamp, Python assumes that the former is in local timezone and thus it shifts it to UTC (because by definition the timestamp is an offset from GMT, also explained by the specific section “What is epoch time?” on that www.epochconverter.com page you referenced), while for the second it knows it already is in that timezone, no shift is needed and it simply computes the offset.
So, it seems to me that your case is different: when you say, at the end, ”my datetime object is a UTC time”, you actually mean that you know that's an UTC time, but Python does not know that, being given a naïve value. On the contrary, the timegm() call assumes that its argument is a GMT time-tuple. In fact, trying your case using explicitly tz-aware value, i.e. moving the UTC datetime above in your timezone, this is what happens:
So, maybe what you really need is another flag, telling RJ what you know, that is that it should assume that the naïve values you have are effectively in UTC, not in your local timezone, so that it shall compute a timegm()-equivalent value.
Oh, got what you mean.
I found the problem. The object that I have is coming from Postgres database using psycopg2 library. As you know we are using ujson to dump these objects. Here is the result:
If there is without timezone object, ujson treats as UTC time!
I think your last combination will tell RJ the same thing? Right? but not sure if you need to add this. You may need to follow timestamp to be consistent with this standard library.
I cloned the branch https://github.com/lelit/python-rapidjson/tree/unix-timestamps and built it but seems the DATETIME_MODE_UNIX_TIME is not available.
@s-alikarimi, see these tests, hopefully the new DATETIME_MODE_NAIVE_IS_UTC option is what you asked... let me know whenever you can try that branch again.
Assuming some positive feedback on this issue, I will propose the inclusion of the related changes.
As said, due to some sloppyness on my part, they are built on top of other unrelated changes, in particular a new number_mode option (supersedes PR #50) and a new global defaultsfeature. If there is any objection I will rebase them in a different branch, otherwise they will land together in a future 0.1.0.
Activity
sontek commentedon Feb 22, 2017
You want to use the
datetime_modeargument.There are also constants for this:
https://github.com/python-rapidjson/python-rapidjson/blob/master/python-rapidjson/rapidjson.cpp#L33-L38
alka2 commentedon Feb 22, 2017
That's only ISO8601 format.
possible to have this built-in?
(ujson is returning unix timestamp by default).
lelit commentedon Feb 22, 2017
While it'd be quite easy to add another flag for that, the fact that it could work only for serialization makes me somewhat unhappy...
BTW, isn't that equivalent to
obj.timestamp()?alka2 commentedon Feb 22, 2017
obj.timestamp()doesn't return UTC time. Rapidjson is already handling ISO8601 format. I think it would be useful to add support for unix timestamp.We are trying to switch from ujson to rapidjson and this is the main problem that we are encountering.
kenrobbins commentedon Feb 23, 2017
@s-alikarimi It's useful to you as a built-in just for the speed factor, I assume?
BTW, I'm curious on your reasons for moving from ujson to rapidjson.
alka2 commentedon Feb 23, 2017
yes. we are processing millions of jsons at a time.
ujson doesn't support the Decimal objects properly especially when more than 9 precisions are needed.
lelit commentedon Feb 23, 2017
I will try to make some experiment on this, next week. Do you think it would require a "combination" of flags, to be able to obtain either the "floating point" value like standard lib
.timestamp()or the "integer" value like you asked above, and of course native/UTC like currentDATETIME_MODE?lelit commentedon Feb 23, 2017
What should happen to
datetime.dateanddatetime.timeinstances?tamjd1 commentedon Feb 23, 2017
I'm also using rapidjson and am interested in this feature. Looking forward to how this plays out.
alka2 commentedon Feb 23, 2017
I think having both flags is good. In our case we need integer (ujson returns integer as well) but to be more precise having the same output as
.timestamp()will be useful. For theDATETIME_MODEUTC should be enough.Not sure about
datetime.dateanddatetime.time.tamjd1 commentedon Feb 23, 2017
@lelit, for
datetime.dateanddatetime.timeinstances, I don't think we need to do anything. They are already formatted. (Also, I don't think anything can be done fordatetime.timeinstances because there isn't enough info to create a unix timestamp from just time).I think those can be left with their default formatting.
The reason we need formatting options for
.timetuple()instance is that it returns an object and not a formatted string.lelit commentedon Feb 23, 2017
Yes, I agree that this "timestamp" serialization of datetimes does not apply to dates and times.
What I can't see right now is a way to tell rapidjson that I want datetimes serialized as timestamps and dates as their ISO8601 representation. In other words, currently I can say
but how can I get the first item formatted as a timestamp instead, while treating the second in the same way? Maybe change those
DATETIME_XXXconstants to be bit flags instead of their current consecutive integer values, so that the last statement would read?
tamjd1 commentedon Feb 23, 2017
That's a good point. Maybe in that case it would be better to format all
datetimeinstances in the same way, for the sake of simplicity and consistency.@s-alikarimi what do you think?
lelit commentedon Feb 23, 2017
Sorry for being thick, but what do you mean with “format all datetime instances in the same way”?
alka2 commentedon Feb 24, 2017
I think @tamjd1 means something like this:
That said convert the today date to datetime object and return its unix timestamp.
13 remaining items
alka2 commentedon Feb 27, 2017
@lelit, for the
timestampandtimegmcomparison:In this case my
datetimeobject is a UTC time and it needs to return 2017-02-27 10:20:00.timegm()returns 2017-02-27 10:20:00 whiletimestamp()returns 2017-02-27 15:20:00.lelit commentedon Feb 27, 2017
Uhm, I'm still confused by your assertions 😈
What I meant is that the
timestamp()method on datetimes does convert the value to GMT before computing the offset, consider:AFAIU, this tells me a different story: the
dtvalue is actually a naïve datetime, that is a value without a timezone, while the latter,dtutc, is clearly a timezone aware datetime, explicitly set to UTC; to compute the timestamp, Python assumes that the former is in local timezone and thus it shifts it to UTC (because by definition the timestamp is an offset from GMT, also explained by the specific section “What is epoch time?” on that www.epochconverter.com page you referenced), while for the second it knows it already is in that timezone, no shift is needed and it simply computes the offset.So, it seems to me that your case is different: when you say, at the end, ”my datetime object is a UTC time”, you actually mean that you know that's an UTC time, but Python does not know that, being given a naïve value. On the contrary, the
timegm()call assumes that its argument is a GMT time-tuple. In fact, trying your case using explicitly tz-aware value, i.e. moving the UTC datetime above in your timezone, this is what happens:Back to RJ, we have
and that seems reasonable to me.
So, maybe what you really need is another flag, telling RJ what you know, that is that it should assume that the naïve values you have are effectively in UTC, not in your local timezone, so that it shall compute a
timegm()-equivalent value.Does this make sense to you?
lelit commentedon Feb 27, 2017
One further consideration:
Maybe we could (ab)use the otherwise strange combination of
IGNORE_TZandUTCflags to mean the above:NB the result of the last statement above is made up, it's not currently implemented!
alka2 commentedon Feb 28, 2017
Oh, got what you mean.
I found the problem. The object that I have is coming from Postgres database using
psycopg2library. As you know we are usingujsonto dump these objects. Here is the result:If there is without timezone object,
ujsontreats as UTC time!I think your last combination will tell RJ the same thing? Right? but not sure if you need to add this. You may need to follow
timestampto be consistent with this standard library.alka2 commentedon Feb 28, 2017
I cloned the branch
https://github.com/lelit/python-rapidjson/tree/unix-timestampsand built it but seems theDATETIME_MODE_UNIX_TIMEis not available.lelit commentedon Feb 28, 2017
Are you sure you checked out and recompiled the right branch?
That constant is definitely there.
alka2 commentedon Feb 28, 2017
My bad :(. Compiled the wrong branch.
Thanks
lelit commentedon Feb 28, 2017
No problem at all! Let me know how it goes!
alka2 commentedon Feb 28, 2017
It went well. The test matches with the current stuff that I have.
Rename DATETIME_MODE_UTC to DATETIME_MODE_SHIFT_TO_UTC and add DATETI…
lelit commentedon Mar 1, 2017
@s-alikarimi, see these tests, hopefully the new DATETIME_MODE_NAIVE_IS_UTC option is what you asked... let me know whenever you can try that branch again.
lelit commentedon Mar 2, 2017
Assuming some positive feedback on this issue, I will propose the inclusion of the related changes.
As said, due to some sloppyness on my part, they are built on top of other unrelated changes, in particular a new
number_modeoption (supersedes PR #50) and a new global defaults feature. If there is any objection I will rebase them in a different branch, otherwise they will land together in a future 0.1.0.Handle “POSIX time” serialization, targeting issue python-rapidjson#61
lelit commentedon Jul 3, 2017
The new feature has been merged in the master branch.