Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/311.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为什么date+;时间增量变成日期,而不是日期时间?_Python_Datetime - Fatal编程技术网

Python 为什么date+;时间增量变成日期,而不是日期时间?

Python 为什么date+;时间增量变成日期,而不是日期时间?,python,datetime,Python,Datetime,在Python中,在混合类型的数字操作中,较窄的类型是,例如int+float→ 浮动: In [57]: 3 + 0.1 Out[57]: 3.1 >>> 3 + 1.0 4.0 >>> 3 + 1 4 但是对于datetime.date,我们有datetime.date+datetime.timedelta→ 日期时间.date,而不是日期时间.datetime: In [58]: datetime.date(2013, 1, 1) + datetim

在Python中,在混合类型的数字操作中,较窄的类型是,例如
int
+
float
→ <代码>浮动:

In [57]: 3 + 0.1
Out[57]: 3.1
>>> 3 + 1.0
4.0
>>> 3 + 1
4
但是对于
datetime.date
,我们有
datetime.date
+
datetime.timedelta
→ <代码>日期时间.date,而不是
日期时间.datetime

In [58]: datetime.date(2013, 1, 1) + datetime.timedelta(seconds=42)
Out[58]: datetime.date(2013, 1, 1)
为什么扩大推理适用于数字,而不适用于
date
/
datetime
/
timedelta


(背景:我正在为一种文件格式编写一个读取例程,其中一个字段是年,一个字段是年中的一天,一个字段是从午夜开始的毫秒。当然,简单而明确的解决方案是
datetime.datetime(2013,1,1,0,0,0)+datetime.timedelta(秒=42)
,但同样可以推断,应该将
3+0.1
重写为
3.0+0.1

当将时间增量和日期相加时,python将只查找时间增量的days属性。因此,如果加上42秒,日期将为0,并且不会影响您的日期。

日期不是datetime的子类;datetime是一种复合类型,将
日期
时间
对象组合为一个。您不能决定从
date
上的操作生成复合类型;
时间
组件不是日期的一部分

另一方面,将整数定义为一种特殊浮点数(
numbers.Integral
numbers.Real
的一个间接子类),因此整数和浮点数之间的混合运算会产生基类型。并且
浮点
不是复合类型,值的小数部分没有单独的类型

如果要从日期操作生成复合类型,则必须是显式的(显式优于隐式)。自己添加一个时间组件:

datetime.combine(yourdate, time.min) + yourdelta
其中,
yourdate
可以通过分析您的年度加上年度输入日期的
date.strtime(“%Y%j”)
生成


备选方案(有时根据
timedelta.seconds
值生成
datetime
对象,或者总是)要求程序员再次打开日期组件(如果这是他们所期望的)。
timedelta
对象不存储任何关于它是否只涉及日期的信息,或者也包括时代。(小时/分钟/秒/微秒数为0这一事实可能只是巧合!)

因此,假设我们有人只想操纵日期,而忽略时间,她会做类似于
my\u new\u date=my\u old\u date+timedelta(days=1)
。当她发现
my_new_date
现在是
datetime
对象而不是
date
对象时,她会非常惊讶,也可能会很恼火。

行为是:

如果
timedelta.days>0
,则日期2在时间上向前移动;如果
timedelta.days<0
,则日期2在时间上向后移动。之后
date2-date1==timedelta.days
timedelta.seconds
timedelta.micross
被忽略。

(我的重点是,自从Python 2.3中添加了
date
对象以来,这种行为就一直存在。)

我还没有找到任何证据来解释为什么这个模块是这样设计的。当然,也有像您这样的用例,您希望表示与一天开始的午夜对应的时间点。在这些情况下,必须来回转换是很烦人的。但是还有其他一些用例,您希望表示一整天(而不仅仅是当天的某个时间点),在这种情况下,您不希望在添加时间增量时意外地以部分天数结束

克里斯·威瑟斯建议改变这种行为,但蒂姆·彼得斯指出:

不兼容的文件化更改总是以这种方式工作的行为不太可能被接受

如果希望对象的行为类似于
datetime.date
,但算术运算返回
datetime.datetime
对象,那么编写一个对象应该不太困难:

from datetime import date, datetime, time, timedelta

def _part_day(t):
    """Return True if t is a timedelta object that does not consist of
    whole days.

    """
    return isinstance(t, timedelta) and (t.seconds or t.microseconds)

class mydate(date):
    """Subclass of datetime.date where arithmetic operations with a
    timedelta object return a datetime.datetime object unless the
    timedelta object consists of whole days.

    """
    def datetime(self):
        """Return datetime corresponding to the midnight at start of this
        date.

        """
        return datetime.combine(self, time())

    def __add__(self, other):
        if _part_day(other):
            return self.datetime() + other
        else:
            return super().__add__(other)

    __radd__ = __add__

    def __sub__(self, other):
        if _part_day(other):
            return self.datetime() - other
        else:
            return super().__sub__(other)

(这是未经测试的,但从这里开始工作应该不难。)

可能的技术原因是Python中的内置类型通常不会从其操作符返回子类,即
date。\uuu add\uuu
不会返回
datetime
。一致的行为要求
date
datetime
可以互换(它们不是)

date+timedelta
行为记录在案,不会改变。如果您想要
datetime
作为结果;从日期创建日期时间:

dt = datetime(d.year, d.month, d.day)
从技术上讲,
date.\uuuuuu add\uuuuu
可以将工作委托给
timedelta.\uuuuu radd\uuuu
timedelta
分别存储
,因此,如果我们想从
date+timedelta
获取
日期
datetime
(这并不意味着我们应该这样做),就可以简单而有效地确定它是否代表天数的整数

<> >问题是<代码> 1 和<代码> 1 是相同的<代码>时间增量(1)< /代码>在这种情况下,即,如果我们允许<代码>日期+时间增量> /代码>返回“代码>日期时间< /代码>,那么如果我们只考虑类型,它应该返回<代码>日期时间< /代码>。 有一个先例是,
int+int
根据结果返回
int
long
,即相同类型的操作可能只根据输入值返回不同类型的值。虽然
date
datetime
不如
int
long
那样可互换

date+timedelta
为某些值返回
date
,为其他值返回
timedelta
将创建
>>> 3 + 1.0
4.0
>>> 3 + 1
4
dt = datetime(year, 1, 1) + timedelta(days=day_of_year - 1, milliseconds=ms)