Date format Swift 3.0 - ios

I have the following code
var calendar = Calendar.current
let unitFlags = Set<Calendar.Component>([.hour, .year, .minute])
calendar.timeZone = TimeZone(identifier: "UTC")!
let startHour = calendar.component(.hour, from: cell.startDate as Date)
let startMinutes = calendar.component(.minute, from: cell.endDate as Date)
let endHour = calendar.component(.hour, from: cell.endDate as Date)
let endMinute = calendar.component(.minute, from: cell.endDate as Date)
print("start hours = \(startHour) : \(startMinutes)")
print("end hours = \(endHour) : \(endMinute)")
So, the result has been right but in the wrong format. It prints 22:30, for instance, which is what I want, but when it comes to numbers less than 10, like 2 AM for instance, it prints 2:0 instead of 02:00. How can I solve this problem? I am trying to link dateformatter to calendar but I can't. I also tried to solve this by taking the approach below:
let myFormatter = DateFormatter()
myFormatter.dateFormat = "HH:mm"
print(myFormatter.string(from: cell.startDate))
print(myFormatter.string(from: cell.endDate))
But it is printing hours that have nothing to do with the exact hours. Have no idea why.
So, any help would be much appreciated!

There are various ways to add the missing leading zero, however the best solution is using the DateFormatter. You have only one problem with the formatter - setting the correct time zone.
// safer than using identifiers that are not actually standardised
myFormatter.timeZone = TimeZone(secondsFromGMT: 0)

Related

How to set specific time on date picker?

I am using date picker and selected datePicker mode as time. When I am loading the date picker it is showing current time.But I want to set default time always 5:00 PM.
I have tried the below way but it didn’t work for me.
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "HH:mm"
dateFormatter.timeZone = .current
if let date = dateFormatter.date(from: "17:00") {
datePicker.date = date
}
Please help me to default to time 5:00PM always. Thank you.
A possible solution is to get the current date and set hour, minute and second accordingly
let fivePM = Calendar.current.date(bySettingHour: 17, minute: 0, second: 0, of: Date())!
datePicker.date = fivePM
Another way is to set the countDownDuration property
datePicker.countDownDuration = 61200 // 17 * 3600
Another possible answer would be:
let cal = Calendar.current
let timeZone: TimeZone = .current
var dateComp = cal.dateComponents(in: timeZone, from: Date())
(dateComp.hour, dateComp.minute, dateComp.second, dateComp.nanosecond) = (17, 0, 0, 0)
let fivePM = cal.date(from: dateComp)
datePicker.date = fivePM
Using this technique you can also get 5pm of the time of another timezone.
Notice that when debugging in Xcode, Xcode will show all dates in the console in the GMT timezone.

cannot convert value of type date to expected argument type date

I am using Swift 3 and trying to get the current hour. Below is the code i have written to get the current hour but it gives an error.
let date = Date()
let calendar = Calendar.current
let hour = calendar.component(.hour, from: date) // error
What could be the reason for this, all the sample code based on Swift 3 shows the same code snippet to get the current hour but it just don't seem to work. Please can anyone point out what could be wrong here. Thanks.
Try this code to get hour in swift 3 :
let calendar = NSCalendar.current
let hour = calendar.component(.hour, from: NSDate() as Date)
Use this code to get a current hour:
let date = Date()
let formatter = NSDateFormatter()
formatter.setFormat = "h"
print(formatter.stringFromDate(date))
Note: I did not run this code in xcode so don't just copy paste.

Why does `ordinality(of: .day, in: .era, for: date)` give the same result for 2 dates in different time zones?

Consider the following code:
import UIKit
let date = Date()
guard let nycTimeZone = TimeZone(abbreviation: "EST"),
let nzTimeZone = TimeZone(abbreviation: "NZDT") else {
fatalError()
}
var nycCalendar = Calendar(identifier: .gregorian)
nycCalendar.timeZone = nycTimeZone
var nzCalendar = Calendar(identifier: .gregorian)
nzCalendar.timeZone = nzTimeZone
let now = Date()
let nycDayOfEra = nycCalendar.ordinality(of: .day, in: .era, for: now)
let nycDayOfYear = nycCalendar.ordinality(of: .day, in: .year, for: now)
var nzDayOfEra = nzCalendar.ordinality(of: .day, in: .era, for: now)
var nzDayOfYear = nzCalendar.ordinality(of: .day, in: .year, for: now)
As I write this, NYC time and Aukland NZ time give different days. That's the case I'm interested in.
With the code above, the results for nycDayOfYear and nzDayOfYear are different (as of this writing I get nycDayOfYear=42 and nzDayOfYear=43.)
That is as expected, and as desired. (I was working to answer a "how do I calculate the number of days of difference in two Dates evaluated in different time zones?" question.)
However, it would take a bunch of messy adjustments to make the above day-of-year calculation and figure out the number of days of difference between those local dates when they span year boundaries.
I therefore tried to do the calculations using ordinality(of: .day, in: .era, for: date).
However, the calculations based on calendar era give the same value regardless of the time zone of the calendar used to make do the calculation.
Why is that?
What would be a simpler way to calculate the number of calendar days difference between two dates WHEN EXPRESSED IN DIFFERENT LOCAL TIME ZONES? Like I said, my code that calculates the day of year would need additional logic added to handle dates that span calendar year boundaries.
Note that this is a different question than "How many days difference is there between 2 dates". In my question I want both dates to be expressed in different local time zones, and I'm interested in the difference in the calendar date of each of those date values.
Martin's comment about calendar calculations over long intervals giving unexpected results is as good an answer as any as to why it doesn't work.
I did come up with code that calculates the desired difference in calendar date values between 2 dates expressed in specific time zones:
let date = Date()
guard let nycTimeZone = TimeZone(abbreviation: "EST"),
let nzTimeZone = TimeZone(abbreviation: "NZDT") else {
fatalError()
}
var nycCalendar = Calendar(identifier: .gregorian)
nycCalendar.timeZone = nycTimeZone
var nzCalendar = Calendar(identifier: .gregorian)
nzCalendar.timeZone = nzTimeZone
let now = Date()
let nycDateComponents = nycCalendar.dateComponents([.month, .day, .year], from: now)
let nzDateComponents = nzCalendar.dateComponents([.month, .day, .year], from: now)
let difference = Calendar.current.dateComponents([.day],
from: nycDateComponents,
to: nzDateComponents)
let daysDifference = difference.days
First I convert the 2 dates to month/day/year DateComponents values using calendars set to their specific time zone.
Then I use the Calendar function dateComponents(_:from:to:), which lets you calculate the difference between 2 DateComponents values, in whatever units you want to use to compare them. (days, in this case)

How to get the specific date in iOS?

I'm working on a project where I have labels and images that change on a daily basis. My idea on how to go about this is I add assets for the images and have multiple files where I take the text (that contains the quote).
Two questions:
Is there a better way of approaching this? (I'm fairly new to iOS, so I'm wondering if this is sound).
How can I take the current day as in: May 22? (I just want to know how to get "22").
you need to use NSDate
// Option 1
let date = NSDate() // today
let dateStringFormatter = NSDateFormatter()
dateStringFormatter.dateFormat = "dd"
let d = dateStringFormatter.stringFromDate(date)
// d = "22"
// Option 2
let d = NSCalendar.currentCalendar().component(.Day, fromDate: NSDate()) // thanks Leo-Dabus
Reference: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSDateFormatter_Class/
Try taking a look at this stackoverflow link on getting the current date.
How to get the current time as datetime
According to noliv in the article you should be able do :
let date = NSDate()
let calendar = NSCalendar.currentCalendar()
let components = calendar.components(.CalendarUnitHour | .CalendarUnitMinute, fromDate: date)
let hour = components.hour
let minutes = components.minute
Hope this helps

SWIFT: How do I add hours to NSDate object

I generate a NSDate object from string.
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
dateFormatter.timeZone = NSTimeZone(abbreviation: "GMT")
let stringToDate = dateFormatter.dateFromString(dateFromService) // 2015-07-20 12:00:43 +0000
I get this string value from webserver. I need to modify for personal device timezone. Want to add hours this stringToDate object but not work
var addHours : Int = 2 // 2 hours will be added
var newDate = stringToDate.dateByAddingTimeInterval(addHours)
Use NSCalendarComponents:
let calendar = NSCalendar.currentCalendar()
let newDate = calendar.dateByAddingUnit(
.CalendarUnitHour, // adding hours
value: 2, // adding two hours
toDate: oldDate,
options: .allZeros
)
Using NSCalendar will account for things like leap seconds, leap hours, etc.
But as Duncan C's answer points out, simply adding hours is definitely the wrong approach. Two time zones won't always be separated by the same amount of time. Again, this is something especially true when we take daylight savings into account. (For example, the United States doesn't start/end daylight savings on the same days as Europe, and Arizona doesn't even do daylight savings).
You're asking the wrong question. This is what's known as an "XY Problem".
You should be asking "How do I display a date string I get from a web server in the user's local time zone."
NSDate represents a date/time in an abstract form that does not contain a time zone. You convert it to a specific time zone for display. Do not try to add/subtract hours to an NSDate to offset for time zones. That is the wrong approach.
The correct answer is simple. Create a second date formatter and don't set it's timezone to GMT. It defaults to the user's local time zone.
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
dateFormatter.timeZone = NSTimeZone(abbreviation: "GMT")
let date = dateFormatter.dateFromString(dateFromService)
let outputDatedateFormatter = NSDateFormatter()
outputDatedateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
//leave the time zone at the default (user's time zone)
let displayString = outputDateFormatter.stringFromDate(date)
println("Date in local time zone = \(displayString)")
For Swift 3 you can use this function:
//get next date by adding hours func
getNewDateAfterAddingHours(hoursToAdd:NSInteger, oldDate:Date) -> Int64 {
let calendar = Calendar.current
let newDate = calendar.date(byAdding: .hour, value: hoursToAdd, to: oldDate)
return Int64((newDate?.timeIntervalSince1970)!)
}
If you are doing it more often, check out library called SwiftMoment (inspired by the same .js library), which allows you to do following (and much more!):
// Create date using moment library
let myDate = moment(myString)
// Add one hour
let dateWithAddedHour = myDate + 1.hours
Moment is a wrapper around NSDate instance, while Duration (which is what you get from Int.hours, Int.minutes etc.) wraps an NSTimeInterval value.
Implementing this should take you just a moment! (Pun intended).

Resources