Comparing two NSDates day, month and year integers - ios

I am trying to compare two NSDates to understand if they are in the same day or not. These are the two dates (the second one is always the current date, NSDate()):
2015-08-23 22:00:00 +0000
2015-08-23 19:13:45 +0000
It seems obvious that the dates are in the same day, as 23 = 23. However I can't seem to be able to establish this in the code. I tried:
1)
let date = tripObject["tripDate"] as! NSDate
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let str = dateFormatter.stringFromDate(date)
let date2 = NSDate()
let dateFormatter2 = NSDateFormatter()
dateFormatter2.dateFormat = "yyyy-MM-dd"
let str2 = dateFormatter2.stringFromDate(date2)
println(". \(str) and \(str2) .")
This gives 2015-08-24 and 2015-08-23
2)
let dateComponents = NSCalendar.currentCalendar().components(.CalendarUnitYear | .CalendarUnitMonth | .CalendarUnitDay, fromDate: tripObject["tripDate"] as! NSDate)
let dateComponents2 = NSCalendar.currentCalendar().components(.CalendarUnitYear | .CalendarUnitMonth | .CalendarUnitDay, fromDate: NSDate())
This gives different day components.
3)
if NSCalendar.currentCalendar().isDate(firstDate!, inSameDayAsDate: secondDate!){
4)
if NSCalendar.currentCalendar().isDateInToday(the NSDate) {
Both 3 and 4 fail.
I am totally lost, any ideas?

NSCalendar has a method isDate:equalToDate:toUnitGranularity: which does exactly what you need
date1 and date2 are the NSDate instances to be compared, the result is Bool
let calendar = NSCalendar.currentCalendar()
calendar.timeZone = NSTimeZone(forSecondsFromGMT: 0)
let datesAreInTheSameDay = calendar.isDate(date1, equalToDate: date2, toUnitGranularity: .CalendarUnitDay | .CalendarUnitMonth | .CalendarUnitYear)
Swift 2:
let datesAreInTheSameDay = calendar.isDate(date1, equalToDate: date2, toUnitGranularity: [.Day, .Month, .Year])
Swift 3:
var calendar = Calendar.current
calendar.timeZone = TimeZone(secondsFromGMT: 0)!
let datesAreInTheSameDay = calendar.isDate(date1, equalTo: date2, toGranularity:.day)

You can convert both dates to start of the day and then use compare method of NSDate to compare them
let date1StartOfTheDay = NSCalendar.currentCalendar().startOfDayForDate(date)
let date2StartOfTheDay = NSCalendar.currentCalendar().startOfDayForDate(date2
if date1StartOfTheDay.compare(date2StartOfTheDay) == OrderedSame
{
//same dates
}

You can use this extension:
extension NSDate {
func isEqualToDate2(dateToCompare : NSDate) -> Bool {
//Declare Variables
var isEqualTo = false
//Compare Values
if self.compare(dateToCompare) == NSComparisonResult.OrderedSame {
isEqualTo = true
}
//Return Result
return isEqualTo
}
}
like:
if date1.isEqualToDate2(date2) {
...
}

Related

Date not getting correctly using NSDate In Swift

I want to print date [1,2,3.... current date] but not getting correct result.
Because when I set first day is "1" in my code, the output in [2,3,4]. And when I set day is "0". It result show correct but show an extra date [1,2,3,4,5]. And today is 4th October 2016, as my time zone.
let date = NSDate()
let components = NSCalendar.currentCalendar().components([.Day , .Month , .Year], fromDate: date)
let year = components.year
let month = components.month
let day = 1 // Output is [2,3,4]
// let day = 0 than o/p [1,2,3,4,5]
dateFormatatter.dateFormat = "MMMM yyyy"
monthNameLabel.text = dateFormatatter.stringFromDate(date)
startDate.year = year
startDate.month = month
startDate.day = day
let startDateNSDate = calendar.dateFromComponents(startDate)!
var dateStart = startDateNSDate // first date
let endDate = NSDate() // last date
dateFormatatter.dateFormat = "dd"
while dateStart.compare(endDate) != .OrderedDescending {
// print(fmt.stringFromDate(date))
// Advance by one day:
dateStart = calendar.dateByAddingUnit(.Day, value: 1, toDate: dateStart, options: [])!
let dateFormat1 = NSDateFormatter()
dateFormat1.dateFormat = "dd-MM-yyyy"
dateArrayCalendar.addObject(dateFormatatter.stringFromDate(dateStart))
dateArrayForCompare.addObject(dateFormat1.stringFromDate(dateStart))
}
And I want result like this [1,2,3,4]
And Same issue Here
let componentsForCompare = calendar.components([.Year, .Month], fromDate: date)
let startOfMonth = calendar.dateFromComponents(componentsForCompare)!
print(startOfMonth)//2016-09-30 18:30:00 +0000
print(dateFormatatter.stringFromDate(startOfMonth)) //01
Its give different Outputs
You need to increment your date at the end of the while loop, rather than at the start:
while dateStart.compare(endDate) != .OrderedDescending {
// print(fmt.stringFromDate(date))
// Advance by one day:
let dateFormat1 = NSDateFormatter()
dateFormat1.dateFormat = "dd-MM-yyyy"
dateArrayCalendar.addObject(dateFormatatter.stringFromDate(dateStart))
dateArrayForCompare.addObject(dateFormat1.stringFromDate(dateStart))
dateStart = calendar.dateByAddingUnit(.Day, value: 1, toDate: dateStart, options: [])!
}

Returns wrong result For printing FIRST AND LAST DATE OF THE MONTH in swift

I need the first and last date of the month using current date. I have found lots of solutions for this. But all gives me wrong answer.
My code:
1. First Date of the month
extension NSDate{
func firstDateOfMonth ()->NSDate{
let calendar = NSCalendar.currentCalendar()
let components = calendar.components([.Year, .Month], fromDate: self)
let startOfMonth = calendar.dateFromComponents(components)!
return startOfMonth
}
func lastDateOfmonth()->NSDate{
let calendar = NSCalendar.currentCalendar()
let comps2 = NSDateComponents()
comps2.month = 1
comps2.day = -1
let endOfMonth = calendar.dateByAddingComponents(comps2, toDate: self, options: [])!
return endOfMonth
}
}
Result looks like this:
print(NSDate().firstDateOfMonth())
print(NSDate().lastDateOfmonth())
Output:
2016-01-31 18:30:00 +0000 // instead of 2016-02-01
// prints the previous month last date
2016-03-02 06:56:17 +0000 // instead of 2016-02-29
// next month date
Please correct if anything is wrong
And I tried this code also
extension NSDate{
func firstDateOfMonths ()->NSDate{
let calendar = NSCalendar.currentCalendar()
let components = calendar.components([.Era, .Year,.Month], fromDate: self)
components.day = 1
let startOfMonth = calendar.dateFromComponents(components)!
return startOfMonth
}
}
Thanks
The first problem is the common problem that you don't understand how NSDate works. NSDate returns UTC, not a date in your time zone. There are hundreds of questions explaining this.
The second problem is you being careless by getting all date components. You are adding one month minus one day to the current date.
The most reliable way to calculate days is rangeOfUnit of NSCalendar
extension NSDate {
func firstDateOfMonth() -> NSDate {
let calendar = NSCalendar.currentCalendar()
// calendar.timeZone = NSTimeZone(forSecondsFromGMT: 0) use this line if you need UTC
var startDate : NSDate?
calendar.rangeOfUnit(.Month, startDate: &startDate, interval: nil, forDate: self)
return startDate!
}
func lastDateOfMonth() -> NSDate {
let calendar = NSCalendar.currentCalendar()
// calendar.timeZone = NSTimeZone(forSecondsFromGMT: 0) use this line if you need UTC
let dayRange = calendar.rangeOfUnit(.Day, inUnit: .Month, forDate: self)
let dayLength = dayRange.length
let components = calendar.components([.Year, .Month, .Day], fromDate: self)
components.day = dayLength
return calendar.dateFromComponents(components)!
}
}
Swift 3+
In Calendar the API is named dateInterval(of:start:interval:for:
extension Date {
func firstDateOfMonth() -> Date {
let calendar = Calendar.current
var startDate = Date()
var interval : TimeInterval = 0
_ = calendar.dateInterval(of:.month, start: &startDate, interval: &interval, for: self)
return startDate
}
func lastDateOfMonth() -> Date {
let calendar = Calendar.current
let dayRange = calendar.range(of:.day, in: .month, for: self)!
let dayLength = dayRange.upperBound
var components = calendar.dateComponents([.year, .month, .day], from: self)
components.day = dayLength
return calendar.date(from:components)!
}
}

NSDateFormatter dateFormatFromTemplate issue

I need to get back the localized format for hours and minutes. The hours works as expected but the minutes returns "m"? Why is it not returning "mm"?
let locale = NSDateFormatter().locale
NSDateFormatter.dateFormatFromTemplate("HH", options: 0, locale:locale)
//Returns "HH" in US English and "H时" in Chinese (Simplified)
NSDateFormatter.dateFormatFromTemplate("mm", options: 0, locale:locale)
//Returns "m" for both???
Have you tried using NSDateComponents?
let date: NSDate = NSDate()
let calendar = NSCalendar.currentCalendar()
let components = calendar.components(NSCalendarUnit.CalendarUnitDay | NSCalendarUnit.CalendarUnitYear | NSCalendarUnit.CalendarUnitMonth | NSCalendarUnit.CalendarUnitHour | NSCalendarUnit.CalendarUnitMinute, fromDate: date)
components.hour = 20
components.minute = 10
if let newDate = calendar.dateFromComponents(components) {
let dateFormatter = NSDateFormatter()
dateFormatter.timeStyle = NSDateFormatterStyle.ShortStyle
dateFormatter.stringFromDate(newDate)
}
Here again as function to retrieve the value you need:
func formattedTimeString(unitToSet: NSCalendarUnit, selectedValue: Int, template: String) -> String?
{
let date: NSDate = NSDate()
let calendar = NSCalendar.currentCalendar()
let components = calendar.components(NSCalendarUnit.CalendarUnitDay | NSCalendarUnit.CalendarUnitYear | NSCalendarUnit.CalendarUnitMonth | NSCalendarUnit.CalendarUnitHour | NSCalendarUnit.CalendarUnitMinute, fromDate: date)
if unitToSet == .CalendarUnitHour
{
components.hour = selectedValue
} else
{
components.minute = selectedValue
}
if let newDate = calendar.dateFromComponents(components) {
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = NSDateFormatter.dateFormatFromTemplate(template, options: 0, locale: NSLocale.currentLocale())
return dateFormatter.stringFromDate(newDate)
}
return nil
}
if let hours: String = formattedTimeString(.CalendarUnitHour, 22, "HH")
{
println(hours) // prints 22
}
if let minutes: String = formattedTimeString(.CalendarUnitMinute, 33, "mm")
{
println(minutes) // prints 33
}
Also available as Gist, if you have further questions.

iOS Swift converting calendar component int month to medium style string month

I want to display calendar in this format
to the user. One option is to use "string range" to get the individual calendar components. The second one is to get it using NSCalendar which to me looks like the better one (is it?). So my code is as below. But there are two problems.
I am not getting the local time form "hour & minute components"
I am getting month in Int. I want it to be in String (month in mediumStyle)
Anyone know how to get what I need? Image attached is what exactly I want to achieve. There I am using three UILabel one for "date", second for "month, year" and third for "time".
Any help would be appreciated.
var inputDateString = "Jun/12/2015 02:05 Am +05:00"
override func viewDidLoad() {
super.viewDidLoad()
let newDate = dateformatterDateString(inputDateString)
let calendar = NSCalendar.currentCalendar()
let components = calendar.components(.CalendarUnitHour | .CalendarUnitMinute | .CalendarUnitMonth | .CalendarUnitYear | .CalendarUnitDay, fromDate: newDate!)
let hour = components.hour
let minutes = components.minute
let month = components.month
let year = components.year
let day = components.day
println(newDate)
println(components)
println(day) // 12
println(month) // 6 -----> Want to have "Jun" here
println(year) // 2015
println(hour) // 2 ------> Want to have the hour in the inputString i.e. 02
println(minutes) // 35 ------> Want to have the minute in the inputString i.e. 05
}
func dateformatterDateString(dateString: String) -> NSDate? {
let dateFormatter: NSDateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "MMM/dd/yyyy hh:mm a Z"
// dateFormatter.timeZone = NSTimeZone(abbreviation: "UTC")
dateFormatter.timeZone = NSTimeZone.localTimeZone()
return dateFormatter.dateFromString(dateString)
}
You can use DateFormatter as follow:
extension Formatter {
static let monthMedium: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "LLL"
return formatter
}()
static let hour12: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "h"
return formatter
}()
static let minute0x: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "mm"
return formatter
}()
static let amPM: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "a"
return formatter
}()
}
extension Date {
var monthMedium: String { return Formatter.monthMedium.string(from: self) }
var hour12: String { return Formatter.hour12.string(from: self) }
var minute0x: String { return Formatter.minute0x.string(from: self) }
var amPM: String { return Formatter.amPM.string(from: self) }
}
let date = Date()
let dateMonth = date.monthMedium // "May"
let dateHour = date.hour12 // "1"
let dateMinute = date.minute0x // "18"
let dateAmPm = date.amPM // "PM"
NSDateFormatter has monthSymbols, shortMonthSymbols and veryShortSymbols properties.
So try this:
let dateFormatter: NSDateFormatter = NSDateFormatter()
let months = dateFormatter.shortMonthSymbols
let monthSymbol = months[month-1] as! String // month - from your date components
println(monthSymbol)
I am adding three types. Have a look.
//Todays Date
let todayDate = NSDate()
let calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian)!
let components = calendar.components(.CalendarUnitYear | .CalendarUnitMonth | .CalendarUnitDay, fromDate: todayDate)
var (year, month, date) = (components.year, components.month, components.day)
println("YEAR: \(year) MONTH: \(month) DATE: \(date)")
//Making a X mas Yr
let morningOfChristmasComponents = NSDateComponents()
morningOfChristmasComponents.year = 2014
morningOfChristmasComponents.month = 12
morningOfChristmasComponents.day = 25
morningOfChristmasComponents.hour = 7
morningOfChristmasComponents.minute = 0
morningOfChristmasComponents.second = 0
let morningOfChristmas = NSCalendar.currentCalendar().dateFromComponents(morningOfChristmasComponents)!
let formatter = NSDateFormatter()
formatter.dateStyle = NSDateFormatterStyle.LongStyle
formatter.timeStyle = .MediumStyle
let dateString = formatter.stringFromDate(morningOfChristmas)
print("dateString : \(dateString)")
//Current month - complete name
let dateFormatter: NSDateFormatter = NSDateFormatter()
let months = dateFormatter.monthSymbols
let monthSymbol = months[month-1] as! String
println("monthSymbol : \(monthSymbol)")
Print Results:
YEAR: 2015 MONTH: 10 DATE: 9
dateString : December 25, 2014 at 7:00:00 AM
monthSymbol : October
Update Swift 5.x Solution:
Today is Monday, 20 April, 2020
let date = Date() // get a current date instance
let dateFormatter = DateFormatter() // get a date formatter instance
let calendar = dateFormatter.calendar // get a calendar instance
Now you can get every index value of year, month, week, day everything what you want as follows:
let year = calendar?.component(.year, from: date) // Result: 2020
let month = calendar?.component(.month, from: date) // Result: 4
let week = calendar?.component(.weekOfMonth, from: date) // Result: 4
let day = calendar?.component(.day, from: date) // Result: 20
let weekday = calendar?.component(.weekday, from: date) // Result: 2
let weekdayOrdinal = calendar?.component(.weekdayOrdinal, from: date) // Result: 3
let weekOfYear = calendar?.component(.weekOfYear, from: date) // Result: 17
You can get an array of all month names like:
let monthsWithFullName = dateFormatter.monthSymbols // Result: ["January”, "February”, "March”, "April”, "May”, "June”, "July”, "August”, "September”, "October”, "November”, "December”]
let monthsWithShortName = dateFormatter.shortMonthSymbols // Result: ["Jan”, "Feb”, "Mar”, "Apr”, "May”, "Jun”, "Jul”, "Aug”, "Sep”, "Oct”, "Nov”, "Dec”]
You can format current date as you wish like:
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let todayWithTime = dateFormatter.string(from: date) // Result: "2020-04-20 06:17:29"
dateFormatter.dateFormat = "yyyy-MM-dd"
let onlyTodayDate = dateFormatter.string(from: date) // Result: "2020-04-20"
I think this is the most simpler and updated answer.
Swift 4.x Solution:
//if currentMonth = 1
DateFormatter().monthSymbols[currentMonth - 1]
Answer:
January
let now = Date()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "LLLL"
let nameOfMonth = dateFormatter.string(from: now)

How to change the first day of week in Swift

I have made a functioning app and part of it includes formatting the date from a date picker.
I need to change the first day of the week as the week days are being displayed as "1" - "7". However, day 1 is currently Sunday and I need day 1 to be Monday and Sunday as day 7.
The code for my date formatter and picker are below:
var chosenDate = self.datePicker.date
var formatter = NSDateFormatter()
formatter.dateFormat = "ewYY"
let day = formatter.stringFromDate(chosenDate)
let dateResult = "\(day)"
DestViewController.date = dateResult
I got all of my date formatting info from this page:
http://www.unicode.org/reports/tr35/tr35-31/tr35-dates.html#Date_Format_Patterns
I just can't seem to work out how to change this first day of the week?
Many thanks in advance
Mark.
Here is good example in how to manipulate date in swift. you can change the code to fit it better for what you may need, but right now it does what you need.
// Playground - noun: a place where people can play
// Setup the calendar object
let calendar = NSCalendar.currentCalendar()
// Set up date object
let date = NSDate()
// Create an NSDate for the first and last day of the month
let components = NSCalendar.currentCalendar().components(NSCalendarUnit.CalendarUnitMonth, fromDate: date)
components.month
// Getting the First and Last date of the month
components.day = 1
let firstDateOfMonth: NSDate = calendar.dateFromComponents(components)!
components.month += 1
components.day = 0
let lastDateOfMonth: NSDate = calendar.dateFromComponents(components)!
var unitFlags = NSCalendarUnit.WeekOfMonthCalendarUnit |
NSCalendarUnit.WeekdayCalendarUnit |
NSCalendarUnit.CalendarUnitDay
let firstDateComponents = calendar.components(unitFlags, fromDate: firstDateOfMonth)
let lastDateComponents = calendar.components(unitFlags, fromDate: lastDateOfMonth)
// Sun = 1, Sat = 7
let firstWeek = firstDateComponents.weekOfMonth
let lastWeek = lastDateComponents.weekOfMonth
let numOfDatesToPrepend = firstDateComponents.weekday - 1
let numOfDatesToAppend = 7 - lastDateComponents.weekday + (6 - lastDateComponents.weekOfMonth) * 7
let startDate: NSDate = calendar.dateByAddingUnit(NSCalendarUnit.CalendarUnitDay, value: -numOfDatesToPrepend, toDate: firstDateOfMonth, options: nil)!
let endDate: NSDate = calendar.dateByAddingUnit(NSCalendarUnit.CalendarUnitDay, value: numOfDatesToAppend, toDate: lastDateOfMonth, options: nil)!
Array(map(0..<42) {
calendar.dateByAddingUnit(NSCalendarUnit.CalendarUnitDay, value: $0, toDate: startDate, options: nil)!
})
"\(components.year)"
//var dateString = stringFromDate(NSDate())// change to your date format
var dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "EE"
var dateString = dateFormatter.stringFromDate(NSDate())
var xdate = dateFormatter.dateFromString(dateString)
//var someDate = dateFormatter.dateString
println(dateString)
this will output::
"Thu"

Resources