3月31日4月1日的Dart/Flutter日期时间差(单位:天)错误

ymdaylpp  于 2023-03-13  发布在  Flutter
关注(0)|答案(5)|浏览(217)

我正在尝试获取从DatePicker中选取的两个日期之间的天数差异。除了一个日期外,此方法工作正常:三月三十一日
当其中一个日期是3月31日时,两个DateTimes之间的天数差错误了1天。我知道这是由于省光,而3月是30.9...天,而不是31天,因此我猜测,错误。但除了手动检查日期是否等于3月31日并在结果中添加一天外,有人知道如何修复此错误吗?
可以在Dart Pad中运行的两个非常简单的示例:

DateTime aprilFirst = DateTime(2019, 3, 30);
DateTime marchThirtyFirst = DateTime(2019, 3, 31);

print(aprilFirst.difference(marchThirtyFirst).inDays); => -1
DateTime marchThirty = DateTime(2019, 4, 1);
DateTime marchThirtyFirst = DateTime(2019, 3, 31);

print(marchThirty.difference(marchThirtyFirst).inDays); => 0

更新

DateTime aprilFirst = DateTime(2019, 4, 1);
print(aprilFirst.add(Duration(days: -1))); => 2019-03-30 23:00:00.000

打印时间应为2019年3月31日23:00:00.000!
我尝试了Günter Zöchbauer的解决方案,使日期时间UTC,但结果完全相同:

DateTime aprilFirst = DateTime(2019, 4, 1).toUtc();
DateTime marchThirty = DateTime(2019, 3, 30).toUtc();
DateTime marchThirtyFirst = DateTime(2019, 3, 31).toUtc();

print(aprilFirst.difference(marchThirtyFirst).inHours); => 23
print(aprilFirst.difference(marchThirtyFirst).inDays); => 0
print(marchThirty.difference(marchThirtyFirst).inHours); => -24
print(aprilFirst.add(Duration(days: -1))); => 019-03-30 22:00:00.000Z
tag5nh1u

tag5nh1u1#

@Günter Zöchbauer让我找到了正确的方法。DateTime(...).toUTC()在差分计算中会失败。然而,使用DateTime.utc(...)构造函数可以做到这一点!

DateTime aprilFirst = DateTime.utc(2019, 4, 1);
DateTime marchThirty = DateTime.utc(2019, 3, 30);
DateTime marchThirtyFirst = DateTime.utc(2019, 3, 31);

print(aprilFirst.difference(marchThirtyFirst).inHours); => 24
print(aprilFirst.difference(marchThirtyFirst).inDays); => 1
print(marchThirty.difference(marchThirtyFirst).inHours); => -24
print(aprilFirst.add(Duration(days: -1))); => 2019-03-31 00:00:00.000Z
aelbi1ox

aelbi1ox2#

不要对本地日期进行日期比较或操作。首先将其转换为UTC。否则夏令时和其他与本地日期时间相关的异常将导致各种令人惊讶的效果。

DateTime aprilFirst = DateTime(2019, 3, 30).toUtc();
DateTime marchThirtyFirst = DateTime(2019, 3, 31).toUtc();

print(aprilFirst.difference(marchThirtyFirst).inDays); => -1

如果结果是DateTime,则可以使用xxx.toLocal()将其转换回来
还有一个构造函数允许创建UTC DateTime,而不是创建本地DateTime然后转换为UTC。

lymgl2op

lymgl2op3#

2021基于答案

extension DateCalcs on DateTime {
  DateTime get dateOnlyUTC => DateTime.utc(this.year,this.month,this.day);
}
txu3uszq

txu3uszq4#

试试这个软件包,Jiffy使用了日期时间差的概念
您可以在此处看到讨论https://github.com/moment/moment/pull/571

var aprilFirst = Jiffy.parseFromList([2019, 3, 30]);
var marchThirtyFirst = Jiffy.parseFromList([2019, 3, 31]);

aprilFirst.diff(marchThirtyFirst, Unit.day); // -1

var marchThirty = Jiffy.parseFromList([2019, 4, 1]);
var marchThirtyFirst = Jiffy.parseFromList([2019, 3, 31]);

marchThirty.diff(marchThirtyFirst, Unit.day); // 1
marchThirty.diff(marchThirtyFirst, Unit.hour); // 24
marchThirty.diff(marchThirtyFirst, Unit.month; // 0
epfja78i

epfja78i5#

您已经发现,由于您的区域设置遵守夏令时,会得到一个意外的结果。Duration内部存储了微秒数;Duration.days是以24小时增量而不是以日历日度量的。从the DateTime documentation
不同时区的两个日期之间的差异仅仅是两个时间点之间的纳秒数。它不考虑日历日。这意味着,如果其间有夏令时变化,当地时间的两个午夜之间的差异可能小于24小时乘以它们之间的天数。如果使用澳大利亚当地时间计算上述差异,差异为7415天零23小时,这仅是由inDays报告的7415整天。
有关Benjamin's answer的更通用版本,请参见https://stackoverflow.com/a/71198806/,该版本计算两个日期之间的天数差,忽略时间(因此也忽略夏令时调整和时区)。

相关问题