Overview
1. 详解 - 0% - 未完成
2. 高效利用 datetime 库计算时间
2.1 求两个时间差的 年,月,日,时,分,秒
刚好今天我要对爬虫爬取设定一个最小周期。
所以重写 一份计算两个 datetime 相差时间的程序,
暂时是我想到最简单的方法了。
对于求差能够用时间的 60 进制移位。
源码 👇
class EasyDeltaDatetime():
from datetime import datetime
def __init__(self, dstDatetime, srcDatetime):
self.dstDatetime = dstDatetime
self.srcDatetime = srcDatetime
self.computer_zero_datetime = datetime(1970, 1, 1, 0, 0, 0)
self.calculate()
def calculate(self):
self.difference = self.dstDatetime - self.srcDatetime
self.meta_datetime = self.computer_zero_datetime + self.difference
def __getattr__(self, attrname):
if attrname in ["year", "month", "day", "hour", "minute", "second"]:
return int(getattr(self.meta_datetime, attrname) - getattr(self.computer_zero_datetime, attrname))
注意:datetime.now()
和 datetime(...)
不能相减的错误
datetime.now()
没有指定 timezone,和通过 datetime(..., tzinfo=...)
实例化的对象相减会出现:
TypeError: can't subtract offset-naive and offset-aware datetimes
如果需要使用 datetime.now()
,则需要指定其 timezone
datetime.now().replace(tzinfo=pytz.timezone("UTC"))
即,将 datetime.now()
替换成上面 👆 这行即可。
2.2 To datetime
2.2.1 转换时间戳(time.time
)为 datetime
time 库 和 datetime 库互换
>>> import time
>>> time.time()
1559545564.3678553
>>> int(time.time())
1559545575
>>> import datetime
>>> datetime.datetime.fromtimestamp(int(time.time()))
datetime.datetime(2019, 6, 3, 15, 8, 15)
>>>
Reference: python学习笔记:time()和datetime()时间模块的基本使用和示例
2.2.2 转换字符串为 datetime
>>> import datetime as dt
>>> dt_ = dt.datetime(2019, 8, 20, 9, 7, 54)
>>> print(repr(dt_))
datetime.datetime(2019, 8, 20, 9, 7, 54)
>>> dt_s = dt_.strftime(format="%Y-%m-%d %H:%M:%S")
>>> print(dt_s) # 字符串
2019-08-20 09:07:54
>>> #### 通过 time 库转换 ####
>>> import time
>>> tdt = time.strptime(dt_s, "%Y-%m-%d %H:%M:%S")
>>> print(repr(tdt))
time.struct_time(tm_year=2019, tm_mon=8, tm_mday=20, tm_hour=9, tm_min=7, tm_sec=54, tm_wday=1, tm_yday=232, tm_isdst=-1)
>>> dt.datetime(*tdt[:-3])
datetime.datetime(2019, 8, 20, 9, 7, 54)
>>> # sort code: dt.datetime(*time.strptime(dt_s, "%Y-%m-%d %H:%M:%S")[:-3])
>>> #### 直接通过 datetime 库提供的接口转换 ####
>>> dt.datetime.strptime(dt_s, '%Y-%m-%d %H:%M:%S')
datetime.datetime(2019, 8, 20, 9, 7, 54)
>>>
3. 使用 “2018-12-27” 格式获取(django-数据库中)最接近的日期的一条数据
核心代码:
try:
visualdatas = UserID.objects.get(
user_id=self.kwargs["user_id"]
).visualdata_set.all()
filter_date = datetime.datetime.strptime(
self.kwargs['date'], "%Y-%m-%d").date()
qs = visualdatas.filter(crawlerDate__year=filter_date.year,
crawlerDate__month=filter_date.month, )
d = {_.crawlerDate.day: _ for _ in qs}
return d[min(d.keys(), key=lambda _: abs(_ - filter_date.day))]
except Exception as e:
print(e, file=sys.stderr)
raise Http404("{}".format(e)) # -[o] update to DRF response type later
Reference:
Python date string to date object: https://stackoverflow.com/questions/2803852/python-date-string-to-date-object👆 对应 line 5, 6
How can I filter a date of a DateTimeField in Django?: https://stackoverflow.com/questions/1317714/how-can-i-filter-a-date-of-a-datetimefield-in-django
👆 对应 line 7, 8
Python 字典推导 - n/a ⇒ 对应 line 9
python build-in function
min
: https://docs.python.org/3/library/functions.html?highlight=min#min👆 对应 line 10
Python
lambda
表达式 - n/a ⇒ 对应 line 10
该段代码为我的一个项目中 DRF 部分的部分代码。
该 核心代码 的所有有关代码:
userid
和 visualdata
的 models.py
部分:
class BaseUserIDInfo(models.Model):
user_id = models.CharField(max_length=128)
name = models.CharField(max_length=512, default='')
class Meta:
abstract = True
class UserID(BaseUserIDInfo, BaseUserInfo):
regitster_date = models.DateTimeField(
'User Regitster Date',
default=datetime(1970, 1, 1, 0, 0, 0, tzinfo=pytz.timezone("UTC")), )
signature = [...the other codes not important...]
class VisualData(models.Model):
user_id = ForeignKey(UserID, on_delete=models.CASCADE)
crawlerDate = DateTimeField('data crowler date', auto_now=True)
originality = IntegerField(default=-1) # 原创文章数量
reprint = IntegerField(default=-1) # 转发数量
[...the other codes not important...]
urls.py
部分:
[...]
urlpatterns = [
[...]
# visualdatas/[{}/]
path("userids/<str:user_id>/visualdatas/",
VisualDataList.as_view(), name="visualdatas_list"),
path("userids/<str:user_id>/visualdatas/<str:date>/",
VisualDataDetail.as_view(), name="visualdatas_detail"),
views.py
部分的该部分完整代码:
class VisualDataViewCommonMixin(object):
serializer_class = VisualDataSerialzier
def get_queryset(self):
_ = get_object_or_404(UserID, user_id=self.kwargs["user_id"])
return _.visualdata_set.all()
class VisualDataList(VisualDataViewCommonMixin, generics.ListCreateAPIView):
class VisualDataDetail(VisualDataViewCommonMixin, generics.RetrieveDestroyAPIView):
def get_object(self):
try:
visualdatas = super().get_queryset()
filter_date = datetime.datetime.strptime(
self.kwargs['date'], "%Y-%m-%d").date()
qs = visualdatas.filter(crawlerDate__year=filter_date.year,
crawlerDate__month=filter_date.month, )
d = {_.crawlerDate.day: _ for _ in qs}
return d[min(d.keys(), key=lambda _: abs(_ - filter_date.day))]
except Exception as e:
print(e, file=sys.stderr)
raise Http404("{}".format(e)) # -[o] update to DRF response type later
考虑 urls.py
和 views.py
实现的功能,以下是运行效果截图:
如果存在当天的数据即显示当天的数据 👇
最接近的日期示例 👇
4. django 中的 datetime
4.1 django model 模型的 DateTimeField 的一些使用细节
🔗 👉 https://blog.csdn.net/qq_29757283/article/details/83188766
4.1.1 为 DateTimeField 设置 default 为计算机元年
🔗 👇
https://blog.csdn.net/qq_29757283/article/details/83188766#_DateTimeField__default__10
4.1.2 使用 标准库 datetime.datetime() 为该 Field 赋值 - timezone 问题
🔗 👇
https://blog.csdn.net/qq_29757283/article/details/83188766#__datetimedatetime__Field__34
4.1.3 在 manage.py shell 中 timezone 显示不一致问题
🔗 👇
https://blog.csdn.net/qq_29757283/article/details/83188766#_managepy_shell__timezone__84
4.1.4 使用 django模型实例渲染模板的 date 显示问题
🔗 👉 https://blog.csdn.net/qq_29757283/article/details/83449253 - 正确的时区时间和显示格式
5. 一些应用
5.1 获取昨天日期
Reference: Python 获取昨天日期
ex. 1:
# 引入 datetime 模块
import datetime
def getYesterday():
today=datetime.date.today()
oneday=datetime.timedelta(days=1)
yesterday=today-oneday
return yesterday
# 输出
print(getYesterday())
ex. 2:
# 引入 datetime 模块
import datetime
def get_yesterday():
yesterday = datetime.date.today() + datetime.timedelta(-1)
return yesterday
# 输出
print(get_yesterday())
Reference
n/a