- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我正在研究 C# DateTime 结构的 C++ 半端口。 (如果您关心 check it out,它是公共(public)领域。)我真的很喜欢让类(class)围绕一个私有(private)的 64 位整数展开。它使许多操作变得 super 简单,并使类保持轻量级。我正在努力的部分是从刻度到年、月或日的计算。目前,I use loops得到正确答案:我一次减去一年的刻度值,这样我就可以在正确的时间减去闰年的刻度值。
好消息是它得到了正确的答案。如果可能的话,我更愿意使用直接的数学方法。我知道 C# 不是开源的,但有没有办法查看 DateTime 的实现?如果没有,我在哪里可以找到将 N 天转换为年月日的数学公式?
请不要对过早的优化发表评论。我没有截止日期。我只是想让它变得更好。这是一种学习体验。
更新 - 对于任何好奇的人,我也确实设法看到了 Mono 中的实现。源码中有纯文本的DateTime.cs。
最佳答案
以下是我之前实现的 Date
结构的摘录。构造函数包含将自 1/1/0001(“序列号”)以来的天数转换为年、月和日的主要逻辑。它基于 System.DateTime
的实际源代码,但我使用了更具描述性的变量名称并添加了注释。
从多个 DateTime
刻度转换时,您需要先除以 TimeSpan.TicksPerDay
以获得序列号。
/// <summary>
/// Represents a date between January 1, 0001 CE, and December 31, 9999 CE, in the proleptic Gregorian calendar.
/// </summary>
public struct Date
{
public const Int32 DaysPerYear = 365;
public const Int32 MonthsPerYear = 12;
private const UInt32 MaxSerialNumber = 3652058;
private const UInt32 December = 11; // 0-based
private const UInt32 DaysInDecember = 31;
private const UInt32 LeapYearInterval1 = 4;
private const UInt32 LeapYearInterval2 = 100;
private const UInt32 LeapYearInterval3 = 400;
private const UInt32 DaysPerLeapYearInterval1 =
DaysPerYear * LeapYearInterval1 + 1; // +1 leap day every 4 years
private const UInt32 DaysPerLeapYearInterval2 =
DaysPerLeapYearInterval1 * (LeapYearInterval2 / LeapYearInterval1) - 1; // -1 leap day every 100 years
private const UInt32 DaysPerLeapYearInterval3 =
DaysPerLeapYearInterval2 * (LeapYearInterval3 / LeapYearInterval2) + 1; // +1 leap day every 400 years
private static readonly UInt32[] DaysOfYear =
new UInt32[(MonthsPerYear + 1) * 2]
{
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365,
0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366,
};
private readonly UInt16 _zeroBasedYear; // 0 to 9998
private readonly Byte _zeroBasedMonth; // 0 to 11
private readonly Byte _zeroBasedDay; // 0 to 30
/// <summary>
/// Initializes a new instance of the <see cref="Date" /> structure to a specified serial number.
/// </summary>
/// <param name="serialNumber">
/// The <see cref="SerialNumber" /> of the new <see cref="Date" />.
/// </param>
/// <exception cref="ArgumentOutOfRangeException">
/// <paramref name="serialNumber" /> is less than 0 or greater than 3652058.
/// </exception>
public Date(Int32 serialNumber)
{
Require.IsBetween("serialNumber", serialNumber, 0, (Int32)MaxSerialNumber);
UInt32 days = (UInt32)serialNumber;
// Find the first year of the 400-year period that contains the date:
UInt32 zeroBasedYear = days / DaysPerLeapYearInterval3 * LeapYearInterval3;
days %= DaysPerLeapYearInterval3;
// Within the 400-year period, advance to the first year of the century that contains the date:
UInt32 centuries = days / DaysPerLeapYearInterval2;
zeroBasedYear += centuries * LeapYearInterval2;
// Special case: If the date is the last day (December 31) of the 400-year period,
// then "centuries" will be out of range because the fourth century has one more day than the others:
if (centuries == LeapYearInterval3 / LeapYearInterval2)
goto December31;
days %= DaysPerLeapYearInterval2;
// Within the century, advance to the first year of the 4-year period that contains the date:
zeroBasedYear += days / DaysPerLeapYearInterval1 * LeapYearInterval1;
days %= DaysPerLeapYearInterval1;
// Within the 4-year period, advance to the year that contains the date:
UInt32 years = days / DaysPerYear;
zeroBasedYear += years;
// Special case: If the date is the last day (December 31) of the 4-year period,
// then "years" will be out of range because the fourth year has one more day than the others:
if (years == LeapYearInterval1)
goto December31;
days %= DaysPerYear;
// Estimate the month using an efficient divisor:
Int32 index = GetDaysOfYearIndex(zeroBasedYear);
UInt32 zeroBasedMonth = days / 32;
// If the estimate was too low, adjust it:
if (days >= DaysOfYear[index + (Int32)zeroBasedMonth + 1])
++zeroBasedMonth;
_zeroBasedYear = (UInt16)zeroBasedYear;
_zeroBasedMonth = (Byte)zeroBasedMonth;
_zeroBasedDay = (Byte)(days - DaysOfYear[index + (Int32)zeroBasedMonth]);
return;
December31:
_zeroBasedYear = (UInt16)(zeroBasedYear - 1);
_zeroBasedMonth = (Byte)December;
_zeroBasedDay = (Byte)(DaysInDecember - 1);
}
private static Int32 GetDaysOfYearIndex(UInt32 zeroBasedYear)
{
return !InternalIsLeapYear(zeroBasedYear) ? 0 : MonthsPerYear + 1;
}
private static Boolean InternalIsLeapYear(UInt32 zeroBasedYear)
{
UInt32 year = zeroBasedYear + 1;
return
(year % LeapYearInterval1 == 0) &&
(year % LeapYearInterval2 != 0 || year % LeapYearInterval3 == 0);
}
}
关于c# - System.DateTime.Year(及其其他属性)是如何实现的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11179335/
我正在尝试使用以下方法对 datetime.datetime 对象列表求和: from datetime import datetime, timedelta d= [datetime.datetim
我正在尝试这个 (datetime.datetime.today()-datetime.datetime.today()).days 给出 -1 并期待值 0 而不是我得到 -1。在这种情况下,我将结
如果我列一个时间增量的列表,平均值比我对这些增量的微秒值求平均时要大。为什么会这样呢?。赠送。这是Linux上的Python3.8.10。
考虑以下片段: import datetime print(datetime.datetime.now() - datetime.datetime.now()) 在 x86_64 Linux 下的 P
如何在 SQLAlchemy 查询中比较 DateTime 字段和 datetime.datetime 对象? 例如,如果我这样做 candidates = session.query(User).f
我收到以下错误: type object 'datetime.datetime' has no attribute 'datetime' 在下面一行: date = datetime.datetime
尝试找出如何将当前日期锁定为变量,以从输入的 self.birthday 中减去。我已经查看了各种示例和链接,但无济于事......建议? from datetime import datetime
您好,我有一些 datetime.datetime 格式的日期,我用它们来过滤带有 Pandas 时间戳的 Pandas 数据框。我刚刚尝试了以下方法并获得了 2 小时的偏移量: from datet
如果您调用 datetime.datetime.now(datetime.timezone.utc) 您会得到类似 datetime.datetime(2021, 9, 8, 1, 33, 19, 6
我正在使用 pywin32 读取/写入 Excel 文件。我在 Excel 中有一些日期,以 yyyy-mm-dd hh:mm:ss 格式存储。我想将它们作为 datetime.datetime 对象
据我所知,自 Unix 纪元(1970-01-01 00:00:00 UTC)以来的秒数在全局各地应该是相同的,因为它固定为 UTC。 现在,如果您所在的时区有几个小时 +/- UTC,为什么这样做会
我正在尝试添加 datetime.datetime 和 datetime.time 以获得一列。我正在尝试结合: import datetime as dt dt.datetime.combine(m
我有一个脚本需要在脚本的不同行执行以下操作: today_date = datetime.date.today() date_time = datetime.strp(date_time_string
我在 AppEngine 上收到 type object 'datetime.datetime' has no attribute 'datetime' 错误,提示日期时间类型,但我的导入是 impo
所以我一直在使用 python 语言制作东西。我遇到了一些不太容易理解的错误: TypeError: 'datetime.datetime' object is not subscriptable (
当我运行时 from datetime import date, time, timedelta date(2012, 11, 1) + timedelta(0, 3600) 结果是 datetime
我的目标是转换 utc进入loc : use chrono::{Local, UTC, TimeZone}; let utc = chrono::UTC::now(); let loc = chron
假设您有一个 datetime.date 对象,例如 datetime.date.today() 返回的对象。 稍后您还会得到一个表示时间的字符串,它补充了日期对象。 在 datetime.datet
我试过了 In [16]: import datetime In [17]: now = datetime.datetime.utcnow() In [18]: isinstance(now, dat
我有以下代码并且收到上述错误。由于我是 python 新手,因此无法理解此处的语法以及如何修复错误: if not start or date < start: start = date 最佳答案 有
我是一名优秀的程序员,十分优秀!