Python 将日期时间序列化为整数时间戳
我希望django rest在序列化时不要将DateTime模型字段转换为字符串日期表示形式Python 将日期时间序列化为整数时间戳,python,django-rest-framework,Python,Django Rest Framework,我希望django rest在序列化时不要将DateTime模型字段转换为字符串日期表示形式 response_date = serializers.DateTimeField(source="updated_at") 我希望这个能作为 1411880508 而不是 “2014-09-28T05:01:48.123” 你会想写一个,像这样: class TimestampField(serializers.Field): def to_native(self, value):
response_date = serializers.DateTimeField(source="updated_at")
我希望这个能作为
1411880508
而不是
“2014-09-28T05:01:48.123”
你会想写一个,像这样:
class TimestampField(serializers.Field):
def to_native(self, value):
epoch = datetime.datetime(1970,1,1)
return int((value - epoch).total_seconds())
要支持写操作,您需要从WritableField
继承,并从\u native()实现
针对DRF 3.x和Python 3.8进行编辑:
class TimestampField(serializers.Field):
def to_representation(self, value):
return value.timestamp()
如果需要JavaScript样式的时间戳:
class JsTimestampField(serializers.Field):
def to_representation(self, value):
return round(value.timestamp()*1000)
虽然我更喜欢Tom Christie给出的答案,因为它更可靠。
为了潜在读者的利益,我决定发布我的解决方案
response_date = serializers.SerializerMethodField('get_timestamp')
def get_timestamp(self, obj):
#times 1000 for javascript.
return time.mktime(obj.updated_at.timetuple()) * 1000
我无法让Tom的例子起作用,而且这些值似乎没有被修改。然而,它给了我一个起点,在阅读之后,我找到了一种产生期望结果的方法:
[方法1]
序列化程序.py
JSON输出:
[{
"id": 1,
"ts": 1475894303
},
{
"id": 2,
"ts": 1475833070
}]
[{
"id": 1,
"ts": "1475890361"
},
{
"id": 2,
"ts": "1475833070"
}]
[方法2]
Tom的解释和前面提到的方法肯定更符合标准(因为结果实际上是integer类型)
但是,一个快速而肮脏的解决方案是指定并将其设置为以秒为单位显示值
注意,这可能无法在Windows计算机上正常工作强>
并可能导致ValueError:无效的格式字符串
要进行尝试,只需在序列化程序字段中包含“format”关键字参数,如下所示:
序列化程序.py
JSON输出:
[{
"id": 1,
"ts": 1475894303
},
{
"id": 2,
"ts": 1475833070
}]
[{
"id": 1,
"ts": "1475890361"
},
{
"id": 2,
"ts": "1475833070"
}]
此外,还可以包括微秒:
timestamp = serializers.DateTimeField(format="%s.%f")
如果要在您自己的解释器中测试功能(验证您的操作系统是否支持%s参数),只需复制以下行:
import datetime
print datetime.datetime.now().strftime('%s') #datetime formatted as seconds for REST
import time #This is just for confirmation
print time.mktime(datetime.datetime.now().timetuple()) #time object result as float
我觉得这个方法与OPs问题有点不一致,因为结果实际上不是integer类型,而是integer/float的字符串表示形式,REST肯定会在值周围加引号。全局配置:
REST_FRAMEWORK = {
'DATETIME_FORMAT': '%s.%f',
}
REST中的结果将是字符串
“1517863184.666435”
“1517863249”
如果希望API中的浮点(或整数)值,则可以使用monkey patching
将文件monkey\u patching.py
放入任何应用程序中,并将其导入应用程序的\uuuu init\uuuuu.py
文件中。即:
app/monkey\u patching.py
#app/monkey_patching.py
import six
from rest_framework import ISO_8601
from rest_framework.fields import DateTimeField
from rest_framework.settings import api_settings
def to_representation_ext(self, value):
if not value:
return None
output_format = getattr(self, 'format', api_settings.DATETIME_FORMAT)
if output_format is None or isinstance(value, six.string_types):
return value
if output_format.lower() == ISO_8601:
value = self.enforce_timezone(value)
value = value.isoformat()
if value.endswith('+00:00'):
value = value[:-6] + 'Z'
return value
# FOR INTEGER RESULT 'DATETIME_FORMAT': '%s',
# return int(value.strftime(output_format))
# FOR FLOAT RESULT 'DATETIME_FORMAT': '%s.%f',
return float(value.strftime(output_format))
DateTimeField.to_representation = to_representation_ext
#app/__init__.py
import app.monkey_patching
app/init.py
#app/monkey_patching.py
import six
from rest_framework import ISO_8601
from rest_framework.fields import DateTimeField
from rest_framework.settings import api_settings
def to_representation_ext(self, value):
if not value:
return None
output_format = getattr(self, 'format', api_settings.DATETIME_FORMAT)
if output_format is None or isinstance(value, six.string_types):
return value
if output_format.lower() == ISO_8601:
value = self.enforce_timezone(value)
value = value.isoformat()
if value.endswith('+00:00'):
value = value[:-6] + 'Z'
return value
# FOR INTEGER RESULT 'DATETIME_FORMAT': '%s',
# return int(value.strftime(output_format))
# FOR FLOAT RESULT 'DATETIME_FORMAT': '%s.%f',
return float(value.strftime(output_format))
DateTimeField.to_representation = to_representation_ext
#app/__init__.py
import app.monkey_patching
使用Django版本2.0.10和Python 3.5.9测试,如前所述,您可以通过以下方式全局设置所有日期时间的时间戳格式:
REST_FRAMEWORK = {
'DATETIME_FORMAT': '%s',
}
但这不适用于常规日期,要使其适用于日期,还必须设置:
REST_FRAMEWORK = {
'DATE_FORMAT': '%s',
}
在python中,时间戳是10位数字。然而,在Javascript中,它是13位数字
因此,如果要在全局配置中返回Javascript格式时间戳,只需在“%s”之后添加“000”:
JS_TIMESTAMP = '%s000'
REST_FRAMEWORK = {
'DATETIME_FORMAT': JS_TIMESTAMP,
'DATE_FORMAT': JS_TIMESTAMP
}
结果如下:1567413479000感谢您的帮助。我是在windows上开发的,因此获取的格式字符串无效,因为windows不支持任何“%s”格式()
因此,我使用了monkey patch-like并稍微调整了解决方案,以返回“%s.%f”的value.timestamp()
,以及“%s”的int(value.timestamp())
。AFAIK日期时间作为一个数字存储在数据库中。我希望得到这个数字,而不是遍历queryset中的所有记录。我担心这和我自己的方法都会对性能产生影响。如果你得到这个答案并使用DRF 3.x,那么to_native
方法现在是to_representation
这个答案很棒!此外,它可以被格式化为浮点吗?我不相信,这也会给我的FilterSet参数带来一些问题,但事实并非如此int@MohammadTorkashvand添加了int和float的信息results@YanQiDong添加了int和float结果的信息这应该是可接受的答案。format=“%s”更干净!