How to set specific time on date picker? - ios

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.

Related

Setting Swift Date minutes with more than 60 returns nil

Very new to IOS, I need to set a Date hour and minutes, I do like this:
let date = Calendar.current.date(bySettingHour: prayerTimeHour, minute: prayerTimeMinutes + Int(adjustement)! , second: 0, of: Date())!
prayerTimeMinutes + Int(adjustement)! in some cases are more than 60 so the app crash because the Date is nil
Let the Calendar do all the math for you. There is no such time as "09:61" and Calendar is telling you so.
// It's not clear that you want the current calendar here. It may not be Gregorian.
let calendar = Calendar(identifier: .gregorian)
// Using ! means you're promising prayerTimeHour and prayerTimeMinutes are valid.
let baseDate = calendar.date(bySettingHour: prayerTimeHour,
minute: prayerTimeMinutes,
second: 0,
of: Date())!
// ! should be safe because the Gregorian calendar will have a date for any number
// of minutes into the future
let adjustedData = calendar.date(byAdding: .minute,
value: adjustement,
to: baseDate)!

Time output not as expected when using iOS SDK DateFormatter on Date set to Jan 1, 1

I have a scenario where dates are being on a server without the day aspect and just the time is needed. Therefore the day element is being stripped away before uploading to the server. Development up to this point (Point 1 in code below) cannot be changed as it is coming from an external source that is already in production.
We are then facing an issue when outputting this time back to the user. The time varies by minutes in different locations, even in the same timezone. Please check the code with comments below.
//1.
//Taking a date with just hours and minutes as I don't need the date.
//The timezone set (Europe/Rome) is different from the machine (Europe/Malta)
//Issue below still occurs if we use the same timezone as the machine.
let date = Date(timeIntervalSinceReferenceDate: 1570168800) //Result: Oct 4, 2050 at 8:00 AM
var calendar = Calendar.current
calendar.timeZone = TimeZone(identifier: "Europe/Rome")!
let comps = calendar.dateComponents([.hour, .minute], from: date)
let strippedDate = calendar.date(from: comps)! //Result: Jan 1, 1 at 8:08 AM
//the date outputted is bypassing the timezone setting and using the machine timezone when stripping out the day
//and keeping hours and minutes alone
//2.
//Outputing the date back to the user in different timezone identifiers
//These timezone identiers are all in the same timezone
let dateFormatter = DateFormatter()
dateFormatter.timeStyle = .short;
dateFormatter.timeZone = TimeZone(identifier: "Europe/Paris")!
var formattedStart = dateFormatter.string(from: strippedDate) //Result: "7:19 AM"
dateFormatter.timeZone = TimeZone(identifier: "Europe/Rome")!
formattedStart = dateFormatter.string(from: strippedDate) //Result: "8:00 AM"
//This above appears correctly as it's coming from the same timezone that set up the starting date
dateFormatter.timeZone = TimeZone(identifier: "Europe/Malta")!
formattedStart = dateFormatter.string(from: strippedDate) //Result: "8:08 AM"
//The above appears the same as the stripped date which is the same as the machine used to create the stripped date
dateFormatter.timeZone = TimeZone(identifier: "Europe/Madrid")!
formattedStart = dateFormatter.string(from: strippedDate) //Result: "6:55 AM"
Referencing this answer, this issue is happening "Because at noon on November 18, 1883, the US and Canada railway companies began using a new, standard time system". Therefore since the date is being saved before this event, this might be the reason why we're getting varied minutes. However I still cannot find a solution to output the correct time.

How to use UILabel and DateFormatter to display the current time?

I am trying to use the UILabel and DateFormatter to display the time (date, min, sec) whenever a user launches the APP.
I currently found this from stackoverflow
let dateFormatterGet = DateFormatter()
dateFormatterGet.dateFormat = "yyyy-MM-dd HH:mm:ss"
but it seems that I have to pass in a time into the formatter. How do I just get the UILabel to display the current time instead of a fixed time?
If you want to show the current time without passing any variables, You do so by:
let dateFormatterPrint = DateFormatter()
dateFormatterPrint.dateFormat = "MMM dd,yyyy"
let exactlyCurrentTime: Date = Date()
print(dateFormatterPrint.stringFromDate(exactlyCurrentTime))
// e.g Set your label text:
myLabel.text = "Current Time: \(dateFormatterPrint.stringFromDate(exactlyCurrentTime))"
For example, If we want: Friday, Nov 16, 2018 | We set: EEEE, MMM d, yyyy
I do also recommend a visit of NSDateFormatter.com to understand how dateFormat works.
Best of luck
label.text = dateFormatter.string(from: Date())

Swift 2.1 DatePicker setDate does not set date to current day and specified time

I am trying to set the minimum date to the current day on the date picker and then for the sake of user experience, set the time to 7pm or 19:00. For some reason it doesn't seem to be working. The minimum date setting works but the time doesn't get set. If I remove the minimum date line, the time gets set to 7pm, but strangely, the date gets set to Monday, Jan 1. Which isn't even this year.
Here's my code below:
datePicker.minimumDate = NSDate()
let calendar:NSCalendar = NSCalendar.currentCalendar()
let components = calendar.components([NSCalendarUnit.Hour, NSCalendarUnit.Minute], fromDate: NSDate())
components.hour = 19
components.minute = 00
datePicker.setDate(calendar.dateFromComponents(components)!, animated: true)
What am I doing wrong here?
Split that last line into:
let date = calendar.dateFromComponents(components)!
datePicker.setDate(date, animated: true)
Then look at the value of date. You'll find it is probably January 1, 2000 at the desired time.
Fix this by adding the year, month, and day components to:
let components = calendar.components([NSCalendarUnit.Hour, NSCalendarUnit.Minute], fromDate: NSDate())
In other words, you need:
let components = calendar.components([NSCalendarUnit.Year, NSCalendarUnit.Month, NSCalendarUnit.Day, NSCalendarUnit.Hour, NSCalendarUnit.Minute], fromDate: NSDate())

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