NSDate获得年/月/日

Ric*_*III 289 objective-c nsdate nscalendar nsdatecomponents

NSDate没有其他信息的情况下,如何获得对象的年/月/日?我意识到我可以用类似的东西做到这一点:

NSCalendar *cal = [[NSCalendar alloc] init];
NSDateComponents *components = [cal components:0 fromDate:date];
int year = [components year];
int month = [components month];
int day = [components day];
Run Code Online (Sandbox Code Playgroud)

但这对于像NSDate年/月/日这样简单的事情来说似乎有很多麻烦.还有其他解决方案吗?

Ita*_*ber 612

因为这显然是我最受欢迎的答案,所以我会尝试编辑它以包含更多信息.

尽管它的名字,NSDate它本身只是标志着机器时间的一个点,而不是一个日期.由NSDatea 指定的时间点与年,月或日之间没有相关性.为此,您必须参考日历.任何给定的时间点将根据您正在查看的日历返回不同的日期信息(例如,在格里高利历和犹太历的日历中日期不同),而格里高利历是最常用的日历.世界 - 我假设 - 我们有点偏见NSDate应该总是使用它.NSDate幸运的是,更加两党合作.


NSCalendar正如你所提到的,获取日期和时间必须通过,但有一种更简单的方法:

NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:[NSDate date]];
Run Code Online (Sandbox Code Playgroud)

这将生成一个NSDateComponents对象,其中包含当天系统日历中当天的日,月和年.(注意:这不一定是当前用户指定的日历,只是默认的系统日历.)

当然,如果您使用的是其他日历或日期,则可以轻松更改.可以在" NSCalendar类参考"中找到可用日历和日历单位的列表.有关详细信息NSDateComponents,请参阅" NSDateComponents类参考".


作为参考,从中访问单个组件NSDateComponents非常简单:

NSInteger day = [components day];
NSInteger month = [components month];
NSInteger year = [components year];
Run Code Online (Sandbox Code Playgroud)

您只需注意:NSDateComponents除非您使用有效信息生成它们(即请求NSCalendar使用NSCalendarUnits 提供该信息),否则不会包含您要求的任何字段的有效信息.NSDateComponents它们本身不包含参考信息 - 它们只是简单的结构,可以存储数字供您访问.例如,如果你想得到一个时代,NSDateComponents你将不得不NSCalendarNSCalendarUnitEra旗帜来提供生成器方法.

  • @Jonny您获得的结果取决于您使用的日历.`NSCalendar`的`+ currentCalendar`方法将返回系统日历,因此如果用户的手机设置为日语或泰语时间模式,您将获得不同的年份.如果要强制使用特定日历系统,请创建日历并使用适当的区域设置对其进行初始化.例如,要强制格里高利历,您将需要使用以下内容:`[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]` (6认同)
  • 对此进行更正后,第一行应该有NSDayCalendarUnit而不是NSWeekCalendarUnit. (3认同)
  • 枚举NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit是DEPRECATED而是使用NSCalendarUnitDay. (2认同)
  • 警告:不要使用 [NSCalendar currentCalendar] 除非您试图向用户显示一个值。考虑到用户可能会遵循佛教日历(现在的年份是 2558 或其他),或任何其他数量的奇数日历。在这些情况下,您不希望您的应用程序中断。除非您有非常具体的理由不使用公历,否则请使用公历。这个错误很难捕捉,因为您和您的测试人员可能都默认使用 gregorian。 (2认同)

小智 50

您可以使用NSDateFormatter获取NSDate的单独组件:

NSDateFormatter *df = [[NSDateFormatter alloc] init];

[df setDateFormat:@"dd"];
myDayString = [df stringFromDate:[NSDate date]];

[df setDateFormat:@"MMM"];
myMonthString = [df stringFromDate:[NSDate date]];

[df setDateFormat:@"yy"];
myYearString = [df stringFromDate:[NSDate date]];
Run Code Online (Sandbox Code Playgroud)

如果您希望获得月份数而不是缩写,请使用"MM".如果你想获得整数,请使用[myDayString intValue];

  • 这实际上并不总是 100% 符合预期。例如,如果 NSDate 为 2013-12-31 00:00:00 +0000,则格式化日期将返回年份 2014,即使日期中的实际数字是 2013 年。 (2认同)

Mik*_*ill 17

只是为了改写Itai的优秀(和工作!)代码,这是一个示例助手类的样子,返回给定NSDate变量的年份值.

正如您所看到的,修改此代码以获取月份或日期非常容易.

+(int)getYear:(NSDate*)date
{
    NSDateComponents *components = [[NSCalendar currentCalendar] components:NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit fromDate:date];

    int year = [components year];
    int month = [components month];
    int day = [components day];

    return year;
}
Run Code Online (Sandbox Code Playgroud)

(我无法相信我们必须在2013年编写我们自己的基本iOS日期函数...)

另一件事:不要使用<和>来比较两个NSDate值.

XCode很乐意接受这样的代码(没有任何错误或警告),但其结果是乐透.您必须使用"比较"功能来比较NSDates:

if ([date1 compare:date2] == NSOrderedDescending) {
    // date1 is greater than date2        
}
Run Code Online (Sandbox Code Playgroud)

  • 指针比较的结果远非抽奖 - 它们具有非常明确的结果,只要您将它们用于它们的目的 - 比较指针,而不是对象. (4认同)
  • 指针比较可能是必要的,但在比较两个日期时它们是不太常见的用例.99.99%的时间任何程序员对比较日期而不是指针更感兴趣.从根本上说,C#和.NET框架旨在使最常见的场景更容易,从而使程序员更有效率,并且在许多情况下,objective-c感觉它会使事情变得更加艰难.如果你有时间阅读800页的每本语言的基础知识,欢呼,但我们其他人都有应用程序按时和按预算交付. (4认同)
  • 这只是一个懒惰的程序员的标志,他不理解他所编写的语言的基础知识。而且,对我来说,在某些情况下,对于 ObjC 对象来说指针比较是必要的 - 特别是如果你正在制作一个自定义容器(尽管ARC 会让事情变得更奇怪)。 (2认同)

Nat*_*bot 14

在Swift 2.0中:

    let date = NSDate()
    let calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian)!
    let components = calendar.components([.Month, .Day], fromDate: date)

    let (month, day) = (components.month, components.day)
Run Code Online (Sandbox Code Playgroud)


Kev*_*vin 11

我正在写这个答案,因为它是唯一的方法,它不会从NSDateComponent变量返回选项和/或强制解包这些变量(也适用于Swift 3).

斯威夫特3

let date = Date()
let cal = Calendar.current
let year = cal.component(.year, from: date)
let month = cal.component(.month, from: date)
let day = cal.component(.day, from: date)
Run Code Online (Sandbox Code Playgroud)

斯威夫特2

let date = NSDate()
let cal = NSCalendar.currentCalendar()
let year = cal.component(.Year, fromDate: date)
let month = cal.component(.Month, fromDate: date)
let day = cal.component(.Day, fromDate: date)
Run Code Online (Sandbox Code Playgroud)

Bonus Swift 3有趣的版本

let date = Date()
let component = { (unit) in return Calendar.current().component(unit, from: date) }
let year = component(.year)
let month = component(.month)
let day = component(.day)
Run Code Online (Sandbox Code Playgroud)


Yuc*_*ong 8

新的iOS 8

ObjC

NSDate *date = [NSDate date];
NSInteger era, year, month, day;
[[NSCalendar currentCalendar] getEra:&era year:&year month:&month day:&day fromDate:date];
Run Code Online (Sandbox Code Playgroud)

迅速

let date = NSDate.init()
var era = 0, year = 0, month = 0, day = 0
NSCalendar.currentCalendar().getEra(&era, year:&year, month:&month, day:&day, fromDate: date)
Run Code Online (Sandbox Code Playgroud)

  • 惊人!@Yuchen Zhong (2认同)

Chr*_*ing 6

从 iOS 8.0(和 OS X 10)开始,您可以使用组件方法来简化获取单个日期组件的过程,如下所示:

int year = [[NSCalendar currentCalendar] component:NSCalendarUnitYear fromDate:[NSDate date]];
Run Code Online (Sandbox Code Playgroud)

应该让事情变得更简单,并希望这能够有效实施。


Joe*_*tti 5

如果您的目标是 iOS 8+,您可以使用新的NSCalendar便捷方法以更简洁的格式实现此目的。

首先创建NSCalendar并使用NSDate所需的任何内容。

NSCalendar *calendar = [NSCalendar currentCalendar];
NSDate *date = [NSDate date];
Run Code Online (Sandbox Code Playgroud)

您可以通过以下方式单独提取组件component:fromDate:

NSInteger year = [calendar component:NSCalendarUnitYear fromDate:date];
NSInteger month = [calendar component:NSCalendarUnitMonth fromDate:date];
NSInteger day = [calendar component:NSCalendarUnitDay fromDate:date];
Run Code Online (Sandbox Code Playgroud)

或者,更简洁地,NSInteger通过以下方式使用指针getEra:year:month:day:fromDate:

NSInteger year, month, day;
[calendar getEra:nil year:&year month:&month day:&day fromDate:date];
Run Code Online (Sandbox Code Playgroud)

有关更多信息和示例,请查看iOS 8 中的 NSDate Manipulation Made Easy。免责声明,我写了这篇文章。