【问题标题】:NSDate get year/month/dayNSDate 获取年/月/日
【发布时间】:2011-04-11 07:50:30
【问题描述】:

在没有其他信息的情况下,如何获取 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];

但是对于像获取NSDate 的年/月/日这样简单的事情来说,这似乎很麻烦。还有其他解决办法吗?

【问题讨论】:

  • 我在使用此代码时遇到了一些麻烦,直到我将第一行更改为“NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];”自从提出这个问题后,API 一定发生了变化。
  • @futureelite7 回滚到修订版 1。那里的代码用于历史目的,是对我最初想法的简单解释。
  • 代码不再有效。你能记下正确的代码吗?
  • @futureelite7 没有。该代码是我第一次尝试的展示,它从未打算工作。如果您觉得这不明确,请随意编辑围绕该代码块的上下文,但不要编辑代码本身。如果您对编辑代码本身感觉非常强烈,那么请将此覆盖到 meta,我们将看看其他 mod 有什么要说的。
  • @mike 这就是你阅读答案而不是问题的原因。

标签: objective-c nsdate nsdatecomponents nscalendar


【解决方案1】:

我之所以写这个答案,是因为它是唯一一种不会从 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)

斯威夫特 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)

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)

【讨论】:

  • 我怎样才能得到一年中的哪一天,例如 4 月 10 日是当天是今年的第 99 天? ——
  • 并确保使用公历,例如日本日历的年份组件返回 1 位数字..
【解决方案2】:

斯威夫特

获取日期的任何元素作为可选字符串的更简单方法。

extension Date {

  // Year 
  var currentYear: String? {
    return getDateComponent(dateFormat: "yy")
    //return getDateComponent(dateFormat: "yyyy")
  }

  // Month 
  var currentMonth: String? {
    return getDateComponent(dateFormat: "M")
    //return getDateComponent(dateFormat: "MM")
    //return getDateComponent(dateFormat: "MMM")
    //return getDateComponent(dateFormat: "MMMM")
  }


  // Day
  var currentDay: String? {
    return getDateComponent(dateFormat: "dd")
    //return getDateComponent(dateFormat: "d")
  }


  func getDateComponent(dateFormat: String) -> String? {
    let format = DateFormatter()
    format.dateFormat = dateFormat
    return format.string(from: self)
  }


}

let today = Date()
print("Current Year - \(today.currentYear)")  // result Current Year - Optional("2017")
print("Current Month - \(today.currentMonth)")  // result Current Month - Optional("7")
print("Current Day - \(today.currentDay)")  // result Current Day - Optional("10")

【讨论】:

    【解决方案3】:

    要获得人类可读的字符串(日、月、年),您可以这样做:

    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateStyle:NSDateFormatterMediumStyle];
    NSString *string = [dateFormatter stringFromDate:dateEndDate];
    

    【讨论】:

      【解决方案4】:

      试试这个。 . .

      代码 sn-p:

       NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:[NSDate date]];
       int year = [components year];
       int month = [components month];
       int day = [components day];
      

      它给出了当前的年、月、日

      【讨论】:

        【解决方案5】:

        斯威夫特 2.x

        extension NSDate {
            func currentDateInDayMonthYear() -> String {
                let dateFormatter = NSDateFormatter()
                dateFormatter.dateFormat = "d LLLL yyyy"
                return dateFormatter.stringFromDate(self)
            }
        }
        

        你可以把它当作

        NSDate().currentDateInDayMonthYear()
        

        输出

        6 March 2016
        

        【讨论】:

          【解决方案6】:

          iOS 8 中的新功能

          ObjC

          NSDate *date = [NSDate date];
          NSInteger era, year, month, day;
          [[NSCalendar currentCalendar] getEra:&era year:&year month:&month day:&day fromDate:date];
          

          斯威夫特

          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)
          

          【讨论】:

          • 太棒了! @钟雨辰
          • 太棒了!更好的语法!
          【解决方案7】:

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

          int year = [[NSCalendar currentCalendar] component:NSCalendarUnitYear fromDate:[NSDate date]];
          

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

          【讨论】:

            【解决方案8】:

            在 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)
            

            【讨论】:

              【解决方案9】:

              这是 Swift 中的解决方案:

              let todayDate = NSDate()
              let calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian)!
              
              // Use a mask to extract the required components. Extract only the required components, since it'll be expensive to compute all available values.
              let components = calendar.components(.CalendarUnitYear | .CalendarUnitMonth | .CalendarUnitDay, fromDate: todayDate)
              
              var (year, month, date) = (components.year, components.month, components.day) 
              

              【讨论】:

                【解决方案10】:

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

                首先创建一个NSCalendar 并使用任何需要的NSDate

                NSCalendar *calendar = [NSCalendar currentCalendar];
                NSDate *date = [NSDate date];
                

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

                NSInteger year = [calendar component:NSCalendarUnitYear fromDate:date];
                NSInteger month = [calendar component:NSCalendarUnitMonth fromDate:date];
                NSInteger day = [calendar component:NSCalendarUnitDay fromDate:date];
                

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

                NSInteger year, month, day;
                [calendar getEra:nil year:&year month:&month day:&day fromDate:date];
                

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

                【讨论】:

                • 我怎样才能得到一年中的哪一天,例如 4 月 10 日是当天是今年的第 99 天? ——
                【解决方案11】:

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

                尽管有它的名字,NSDate 本身只是标记机器时间中的一个点,而不是日期。 NSDate 指定的时间点与年、月或日之间没有关联。为此,您必须参考日历。任何给定的时间点都会根据您正在查看的日历返回不同的日期信息(例如,公历和犹太历中的日期并不相同),而公历是世界上使用最广泛的日历世界 - 我假设 - 我们有点偏向于 NSDate 应该始终使用它。 NSDate,幸运的是,它是两党合作的。


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

                NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:[NSDate date]];
                

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

                当然,如果您使用不同的日历或日期,您可以轻松更改它。可以在NSCalendar Class Reference 中找到可用日历和日历单位的列表。有关NSDateComponents 的更多信息,请访问NSDateComponents Class Reference


                作为参考,从NSDateComponents 访问单个组件相当简单:

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

                您只需要注意:NSDateComponents 不会包含您要求的任何字段的有效信息,除非您使用该有效信息生成它们(即请求 NSCalendar 以通过 NSCalendarUnits 提供该信息)。 NSDateComponents 本身不包含参考信息 - 它们只是简单的结构,包含供您访问的数字。例如,如果您还想从NSDateComponents 中获得一个时代,则必须将NSCalendar 的生成器方法与NSCalendarUnitEra 标志一起提供。

                【讨论】:

                • 对此进行更正,第一行应该有 NSDayCalendarUnit 而不是 NSWeekCalendarUnit。
                • @Erik 您使用的是哪个日历?代码?
                • @Jonny 您获得的结果取决于您使用的日历。 NSCalendar+currentCalendar 方法将返回系统日历,因此如果用户的手机设置为日文或泰文时间模式,您将获得不同的年份。如果您想强制使用特定的日历系统,请创建一个日历并使用正确的语言环境对其进行初始化。例如,要强制使用公历,您需要使用以下内容:[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]
                • 枚举 NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit 已弃用,请改用 NSCalendarUnitDay。
                • 警告:不要使用 [NSCalendar currentCalendar] 除非您试图向用户显示值。考虑用户可能会遵循佛教日历(现在是 2558 年或其他年份),或任何其他数量的奇数日历。您不希望您的应用程序在这些情况下中断。除非您有非常具体的理由不这样做,否则请使用公历。这个错误很难发现,因为您和您的测试人员可能都默认使用 gregorian。
                【解决方案12】:

                我就是这样做的....

                NSDate * mydate = [NSDate date];
                
                NSCalendar * mycalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
                
                NSCalendarUnit units = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay;
                
                NSDateComponents * myComponents  = [mycalendar components:units fromDate:mydate];
                
                NSLog(@"%d-%d-%d",myComponents.day,myComponents.month,myComponents.year);
                

                【讨论】:

                  【解决方案13】:
                      NSDate *currDate = [NSDate date];
                      NSCalendar*       calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
                      NSDateComponents* components = [calendar components:NSDayCalendarUnit|NSMonthCalendarUnit|NSYearCalendarUnit fromDate:currDate];
                      NSInteger         day = [components day];
                      NSInteger         month = [components month];
                      NSInteger         year = [components year];
                      NSLog(@"%d/%d/%d", day, month, year);
                  

                  【讨论】:

                  • 这显然没有给我作为整数的年、月或日,这是我在 OP 中要求的。 -1.
                  • Richard J. Ross III:我刚刚修复了它,对不起,因为我的答案丢失了你的问题。
                  【解决方案14】:

                  您可以使用 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]];
                  

                  如果您希望获取月份编号而不是缩写,请使用“MM”。如果您想获取整数,请使用[myDayString intValue];

                  【讨论】:

                  • 扩展了他的this gist。玩得开心——你可以把它放到你的代码中。
                  • 解决了我使用日期在字典中查找的问题 :) 谢谢!
                  • 这实际上并没有像预期的那样一直 100% 工作。例如,如果 NSDate 是 2013-12-31 00:00:00 +0000,那么格式化的日期将返回 2014 年,即使日期中的实际数字是 2013 年。
                  • 我怎样才能得到一年中的哪一天,例如 4 月 10 日是当天是今年的第 99 天? ——
                  【解决方案15】:

                  尝试以下方法:

                      NSString *birthday = @"06/15/1977";
                      NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
                      [formatter setDateFormat:@"MM/dd/yyyy"];
                      NSDate *date = [formatter dateFromString:birthday];
                      if(date!=nil) {
                          NSInteger age = [date timeIntervalSinceNow]/31556926;
                          NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:date];
                          NSInteger day = [components day];
                          NSInteger month = [components month];
                          NSInteger year = [components year];
                  
                          NSLog(@"Day:%d Month:%d Year:%d Age:%d",day,month,year,age);
                      }
                      [formatter release];
                  

                  【讨论】:

                    【解决方案16】:

                    只是为了改写 Itai 的优秀(并且有效!)代码,这是一个示例帮助类的样子,它返回给定 NSDate 变量的 year 值。

                    如您所见,修改此代码以获取月份或日期非常简单。

                    +(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;
                    }
                    

                    (我不敢相信我们必须像这样在 2013 年编写自己的基本 iOS 日期函数......)

                    另一件事:永远不要使用 来比较两个 NSDate 值。

                    XCode 很乐意接受这样的代码(没有任何错误或警告),但它的结果是彩票。您必须使用“比较”功能来比较 NSDates:

                    if ([date1 compare:date2] == NSOrderedDescending) {
                        // date1 is greater than date2        
                    }
                    

                    【讨论】:

                    • 指针比较的结果远非彩票 - 他们有非常明确的结果,只要你将它们用于它们的目的 - 比较指针,而不是对象。
                    • 它可能不是彩票,但 C# 的 DateTime 更直观。在 iOS 中,小于运算符真的应该比较两个 NSDate ......有人真的想比较两个 NSDate 变量的指针吗?至少,XCode 显示一个警告来询问这是否真的是用户真正的意思。
                    • 这只是一个懒惰的程序员的标志,他不了解他所写语言的基础知识。而且,对我来说,在某些情况下,ObjC 对象需要指针比较 - 特别是如果你'正在制作一个自定义容器(尽管使用 ARC 会变得更奇怪)。
                    • 我一定是个懒惰的程序员,不懂基本原理,但迈克给了我一个很好的建议!
                    • 指针比较可能是必要的,但在比较两个日期时,它们是不太常见的用例。 99.99% 的情况下,任何程序员都会对比较日期而不是指针更感兴趣。从根本上说,C# 和 .NET 框架旨在简化最常见的场景,从而提高程序员的工作效率,而且在许多情况下,objective-c 感觉像是故意让事情变得更加艰巨。如果您有时间阅读一本 800 页的关于每种语言基础知识的书,那就干杯吧,但我们其他人都有可以按时按预算交付的应用程序。
                    【解决方案17】:

                    如果您希望从 NSDate 获取单个 NSDateComponents,您肯定需要 Itai Ferber 建议的解决方案。但是如果你想要to go from NSDate directly to an NSString, you can use NSDateFormatter

                    【讨论】:

                      猜你喜欢
                      • 2012-02-12
                      • 1970-01-01
                      • 2011-12-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2014-12-18
                      • 1970-01-01
                      相关资源
                      最近更新 更多