23

任何人都知道 NSDate 的最小和最大可能值是多少?

4

4 回答 4

46

使用[NSDate distinctFuture][NSDate distinctPast]

于 2014-05-28T07:44:52.453 回答
3

编辑答案:

我认为我发现最小日期值是0001-01-01 00:00:00 + 0000(给定下面的代码)但是正如下面的评论中指出的那样,这仅适用于当前时代 (即 AD)。NSDate 值可能会低于此值,但您看到的 NSLog 结果可能不是您所期望的,因此我建议您在此处查看其他答案并忽略我的无知。

原始答案:

我相信我发现最小日期值是0001-01-01 00:00:00 + 0000

在 NSLog'ing 和解析值时需要非常小心,以确保您的时区不会稍微倾斜日期值。

我将在下面尝试和演示:

NSDateFormatter *dateFormatter1 = [[NSDateFormatter alloc] init];
[dateFormatter1 setDateFormat:@"yyyy-MM-dd hh:mm:ss z"];

NSDateFormatter *dateFormatter2 = [[NSDateFormatter alloc] init];
[dateFormatter2 setDateFormat:@"yyyy-MM-dd HH:mm:ss z"];

NSDateFormatter *dateFormatter3 = [[NSDateFormatter alloc] init];
[dateFormatter3 setDateFormat:@"yyyy-MM-dd HH:mm:ss z"];
[dateFormatter3 setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];

NSDate *date1 = [NSDate dateWithTimeIntervalSince1970:-62135596800];
NSLog(@"date1 = %@", date1);
NSLog(@"date1 via dateFormatter1 = %@", [dateFormatter1 stringFromDate:date1]);
NSLog(@"date1 via dateFormatter2 = %@", [dateFormatter2 stringFromDate:date1]);
NSLog(@"date1 via dateFormatter3 = %@", [dateFormatter3 stringFromDate:date1]);

NSDate *date2 = [NSDate dateWithTimeIntervalSince1970:-62135596800 - 100]; // The - 100 makes no difference
NSLog(@"date2 = %@", date2);
NSLog(@"date2 via dateFormatter1 = %@", [dateFormatter1 stringFromDate:date2]);
NSLog(@"date2 via dateFormatter2 = %@", [dateFormatter2 stringFromDate:date2]);
NSLog(@"date2 via dateFormatter3 = %@", [dateFormatter3 stringFromDate:date2]);

这会产生以下输出(在我的 iPad 上给定其特定时区):

date1 = 0001-01-01 00:00:00 +0000
date1 via dateFormatter1 = 0001-12-31 11:58:45 GMT-00:01:15
date1 via dateFormatter2 = 0001-12-31 23:58:45 GMT-00:01:15
date1 via dateFormatter3 = 0001-01-01 00:00:00 GMT
date2 = 0001-12-31 23:58:20 +0000
date2 via dateFormatter1 = 0001-12-31 11:57:05 GMT-00:01:15
date2 via dateFormatter2 = 0001-12-31 23:57:05 GMT-00:01:15
date2 via dateFormatter3 = 0001-12-31 23:58:20 GMT

请注意 date2 以及如何减去额外的 100 秒并没有减少日期的值,但实际上似乎增加了它。显然 NSDate 的内部工作方式有些特殊,时间调整了 100 秒,但这可能会使日期和月份出现偏差,也许是因为它不能再低了?

于 2013-03-01T14:17:11.640 回答
2

最大值应该是:5828963-12-20 00:00:00 +0000 因为

NSDate *dateSinceNow = [NSDate dateWithTimeIntervalSinceNow:DBL_MAX];
NSDate *dateSindeReferenceDate = [NSDate dateWithTimeIntervalSinceReferenceDate:DBL_MAX];
NSLog(@"min: %@, max: %@", dateSinceNow, dateSindeReferenceDate);

是一样的。

我得到的最低限度是:0001-01-01 00:00:00 +0000

因为这是我尝试时得到的:

NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:@"yyyy-MM-dd hh:mm:ss"];
[df setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
NSDate *myDate = [df dateFromString: @"0001-01-01 00:00:00"];
NSLog(@"%@", myDate);

但正如 davedelong 所指出的,这是当前时代

因此,如果您尝试使用 - DBL_MAX 的第一个示例,您会得到:41221-07--2147483641 00:00:00 +0000。不知道这是什么时代。。。

于 2013-03-01T12:17:00.357 回答
0

OP 的真正问题(在他对自己的 OP 的评论中澄清)大约是 1/1/1。正如您在我的TL;DR 中的 Playground 中看到的那样;,如果您没有指定 a with Era ,Apple 会打印“31 Dec 0001”而不是“31 Dec 0001 BCDateFormatter ” ,因此如果 OP 的 1/1/1 AD 很容易成为 31/1/1 BC(前一天)本地时区不是 UTC。

NSDate / Date可以有效地使用到过去约 3000 万年,但NSDateComponents / DateComponents操作失败,日期在公元前 4500 年之前。请继续阅读以了解详细信息...

TL;博士;

正如一些评论员和受访者所指出的,[NSDate distantPast](或Date.distantPast在 Swift 中)是由 API 提供的,但是,这不是最低限度的NSDate/ Date- 它只是方便业务逻辑,因为很少有应用程序需要对 BCE 进行计算(请注意.distantFuture也是任意的——它是公元 4001 年 1 月 1 日)。

其他受访者 (@peko) 已经处理过真正的“distantFuture”最大值,但没有人完全探索过最小值。

那么,Date当您实际上给它日期之前会做什么.distantPast呢?这是一个小操场:

// Swift 5 Playground
import Foundation

var d = Date.distantPast // "31 Dec 1 at 23:58"
// However, that's the default print, which *does not* include Era

let df = DateFormatter()
df.dateFormat = "EEEE dd MMMM yyyy G" // "G" is Era

print(df.string(from: d)) // "Friday 31 December 0001 BC\n"

// What happens when we go lower?
d = d.addingTimeInterval(-1e12) // "29 Nov 31689 at 22:12"
print(df.string(from: d)) // Thursday 29 November 31689 BC\n"

// Lower still?
d = d.addingTimeInterval(-1e14) // "18 Feb 3200497 at 12:25"
print(df.string(from: d)) // "Tuesday 18 February 3200497 BC\n"

// But it breaks here...
d = d.addingTimeInterval(-1e15) // ""
print(df.string(from: d)) // "\n"

所以NSDate/Date在过去至少有约 3000 万年的有效时间。

然而,我在比/可以处理的更近的时间里进行计算时遇到了困难。NSDateDate

具体来说,Calendar'.dateComponents(unitFlags, from: date)失败(并打印如下所示的错误消息),早于公元前 4713 年左右。

2021-12-03 19:15:48.885955+0000 Tempus II[61381:6027263] [general] CFAbsoluteTime -268229356861.914001 超出日历计算范围。

...“-268229356861.914001”是公元前 6500 年,但任何尝试对DateComponent公元前 4713 年之前的任何事物进行计算都会给出类似的信息,并且计算将是错误的!

这是另一个您自己尝试的小游乐场:

let df = DateFormatter()
df.dateFormat = "EEEE dd MMMM yyyy G" // "G" is Era

// 500BC -> by 1000 years, which works
let dc500 = DateComponents(calendar: .autoupdatingCurrent,
                           era: 0,
                           year: 500)
var d = Calendar.autoupdatingCurrent.date(from: dc500)!
print(df.string(from: d)) // Thursday 01 January 0500 BC\n"

d = Calendar.autoupdatingCurrent.date(byAdding: delta, to: d)!
print(df.string(from: d)) // "Monday 01 January 0501 AD\n"
// *** NB 501AD is the RIGHT answer for 500BC + 1000, as there
// *** was no year 0

d = Calendar.autoupdatingCurrent.date(byAdding: delta, to: d)!
print(df.string(from: d)) // "Friday 01 January 1501 AD\n"


// 5000BC -> by 2000 years, which doesn't work
delta = DateComponents(calendar: .autoupdatingCurrent,
                       year: 2000)

let dc5000 = DateComponents(calendar: .autoupdatingCurrent,
                            era: 0,
                            year: 5000)
d = Calendar.autoupdatingCurrent.date(from: dc5000)!
print(df.string(from: d)) // "Sunday 01 January 5000 BC\n"

d = Calendar.autoupdatingCurrent.date(byAdding: delta, to: d)!
print(df.string(from: d)) // "Tuesday 01 January 2713 BC\n"
// *** WRONG!

d = Calendar.autoupdatingCurrent.date(byAdding: delta, to: d)!
print(df.string(from: d)) // "Wednesday 01 January 0713 BC\n"
// *** Back on track again

d = Calendar.autoupdatingCurrent.date(byAdding: delta, to: d)!
print(df.string(from: d)) // "Thursday 01 January 1288 AD\n"
// *** Again, correct 
// 713 -> 1BC + 1 AD -> 1288 = 1288 + 713 - 1 = 2000

ps

不要Date在不了解 , 和 ! 的情况下在TimeZone业务Calendar逻辑中DateComponents使用DateFormatter

于 2021-12-03T20:10:13.927 回答