5

The following will create an NSDateComponents object containing day and weekday but not hour:

var today = NSDate()
var gregorian = NSCalendar(calendarIdentifier: NSGregorianCalendar)
var flags: NSCalendarUnit = .DayCalendarUnit | .WeekdayCalendarUnit
var components = gregorian.components(flags, fromDate: today)

// valid
components.day
components.weekday
// invalid
components.hour

In order to have hour, I would have to |-in the .HourCalendarUnit like this:

flags = flags | .HourCalendarUnit

Is there a flag to specify all flags? Or do I just have to manually | them all in if I want an NSDateComponents to have them all?

Alternatively, and ideally, I would like to just be able to say today.hour without using NSDateComponents at all. Does such a class exist?

Chris Redford
  • 16,982
  • 21
  • 89
  • 109
  • 2
    Note: .DayCalendarUnit, .WeekdayCalendarUnit and .HourCalendarUnit are deprecated and should be changed for .CalendarUnitDay, .CalendarUnitWeekday, CalendarUnitHour and so on – Leo Dabus Dec 02 '14 at 07:27

1 Answers1

10

NSCalendarUnit can be initialized with an UInt, so this gives you all possible components:

var today = NSDate()
var gregorian = NSCalendar(calendarIdentifier: NSGregorianCalendar)
var flags = NSCalendarUnit(UInt.max)
var components = gregorian.components(flags, fromDate: today)

A today.hour method does not exist because the calculation cannot be done without knowing the time zone to use for the conversion.

Update for Swift 2:

let gregorian = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
let flags = NSCalendarUnit(rawValue: UInt.max)
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • 1
    I disagree that time zone is a limitation. `NSDate` already uses the local time zone by default. You can see this in the printed preview in swift playgrounds. It could just use a default timezone and default gregorian calendar. I know it isn't impossible because I am writing my own `Date` class that does it. – Chris Redford Aug 06 '14 at 15:20
  • 1
    @ChrisRedford: Yes, I did not express myself well. In the Foundation frameworks, NSDate represents just an absolute point in time, without any knowledge of time zone, days, month etc. All calendrical calculation are done with NSCalendar (which is more or less a wrapper to the ICU calendar functions). There are also utility methods such as descriptionWithCalendarFormat(), but no hour() method. – Martin R Aug 06 '14 at 16:46
  • You can get only the hour also using descriptionWithCalendarFormat() but it will return String format %H (00-23) or %I (01-12) – Leo Dabus Dec 02 '14 at 05:25
  • I read it and I understood what you said but it is easy to implement an hour() function and there is no need to use TimeZone – Leo Dabus Dec 02 '14 at 06:00
  • Anyone figure out how to do this in Swift 3.0 yet? Just did myself. ```NSCalendar.Unit(rawValue: UInt.max)``` – Andrew Oct 05 '16 at 20:25
  • @AndrewAnthonyGerst: You can bridge `Calendar` back to `NSCalendar`, so this seems to work: `(gregorian as NSCalendar).components(NSCalendar.Unit(rawValue: UInt.max), from: today)`. – There may be a nicer method though. – Martin R Oct 05 '16 at 20:36