Set time (Hours, minutes) on Date object - ios

I'm trying to let the user pick a date from the calendar and then set what time they want to be reminded on that date.
I get the date from this code:
func handleCellSelected(view: JTAppleCell?, cellState: CellState){
guard let validCell = view as? CalendarCell else {return}
if validCell.isSelected{
validCell.selectedView.isHidden = false
if userPickedDate {
self.formatter.dateFormat = "YYYY MMMM dd, HH:mm"
dateSelected.text = formatter.string(from: cellState.date)
This produces an output of the selected date with 00:00 in time. I want the user to be able to change the hours and minutes somehow, probably with a picker, to later be reminded on that date and time. Any ideas on how to change the hours and minutes inside the cellState.date?

You can set the datepicker's date to the cellState's date, and then you can only allow the datepicker to select hours and minutes. The resulting date from the datepicker will be the selected time on the date that you initially set it to. You can then grab that date and save it however you'd like.

Related

How to schedule and repeat local notification

I'm trying to make an application to help quitting smoking,
I need the user to enter his first cigarette time, and the time between each cigarette , and finally the added time to increase time between each cigarette. and at this time I send a local notification.
Ex: let say his first cigarette at 7:00 AM and he smokes 1 cigarette every 1 Hr and he want to add extra 10 min.
so 1st cigarette : 7:00
2nd : 8:10/
3rd : 9:20/
4th :10:30 .. etc
I tried a lot of solutions but I have some problems about date format that I got from picker views, I need them to be like "hh:MM a"
Any help?
To get a date in a different format, you can create a NSDate from a Date object and then use NSDateFormatter to format:
let date=NSDate(timeInterval: 0, since: yourDate)
let dateFormatter=DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US")
dateFormatter.setLocalizedDateFormatFromTemplate("hh:mm a")
String dateString=dateFormatter.string(from: date)
You can get the initial date object from the UIDatePicker or when it changes and a method is called in its delegate.
first create a date object with
let date = Date(timeIntervalSinceNow: 3600) // it may be any date whatever you want
To create the trigger from the date components:
let triggerDaily = Calendar.current.dateComponents([hour,.minute,.second,], from: date)
Now pass that date in UNCalendarNotificationTrigger with repeats true
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDaily, repeats: true)
Create a date with time :
let formatter = DateFormatter()
formatter.dateFormat = "yyyy/MM/dd HH:mm"
let someDateTime = formatter.date(from: "2016/10/08 22:31") // put your date and time here
if Locale specific time :
formatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
Well the solution suggested isn't elegant enough, so you have to create one notification for every hour, instead use this trigger
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: (60*60) + (10*60), repeats: true)
60*60 being the hour you mentioned and 10*60 being the 10 minute, set repeating to true and viola, your notification now triggers every 70 minutes.

How to identify the same time in both DST / non-DST for iPhone in Swift?

In swift, the current time Date() is retrieved from the system time of iPhone. Using DateFormatter() seems to work the same way with a given string. For example, using the following method, we can get the same result as calling Date() right when the iPhone time reaches 2018/04/01 02:00:00
let MY_DATE_STRING = "2018/04/01 02:00:00"
var resultTime: Date {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy/MM/dd HH:mm:ss"
formatter.timeZone = TimeZone.current
return formatter.date(from: MY_DATE_STRING)!
}
My question is, let's say, if 2018/04/01 2:00:00 is the end of daylight saving time, so the iPhone will have two 2am on that day -- one is with DST, while the other is not. These two times should have different UTC timestamp though. If currently the iPhone(or my self-defined MY_DATE_STRING) just enters the second 2am, which is a non-DST one, how could I set the TimeZone or other attributes so that the Date() or the given MY_DATE_STRING could generate the timestamp of second 2am instead of the first one?

All users to have exactly the same date and time

So I would like that all my users would have the same date and time no matter their location. Even if they have changed date and time settings the date and time in the application would not change.
At the moment I have constructed a string which is based on every user's 'iPhone time'.
let todaysDate: String = {
let date = Date()
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
let result = formatter.string(from: date)
return result
}()
My wish is that every user would have EET (Eastern Europe Time).
Just set the time zone of your dateformatter to EET if you need the time/date to be independent of user location.
formatter.timeZone = TimeZone(abbreviation: "EET")
However, Date() returns the current device time, so if the user changes their date/time setting, you would get wrong results. To always get a correct data, you have to rely on a date fetched from a reliable server.

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

UIDatePicker of type "Date & Time" only returns Date and not Time

I'm developing an iOS app which uses a UIDatePicker. The mode is "Date and Time" so the user can pick a date and time from the same picker. You can actually see Day,Time,Hour,Min,AM/PM in the picker.
The problem is, when I try to extract the time AND date (both important), I only get the date printed out even though it's a "Date AND Time" picker (according the Xcode and what I see during runtime).
Here is the code:
let dateFormatter = NSDateFormatter()
dateFormatter.dateStyle = NSDateFormatterStyle.ShortStyle
var date = dateFormatter.stringFromDate(sender.date)
println(date)
dateTimeLabel.text = date
dateTimeLabel.textColor = UIColor.blackColor()
It's identical to other examples I see online but I just don't understand why they get Time and Date and I only get the Date. I need the time as well!
The NSDateFormatterStyle.ShortStyle will return something like "6/20/2015, 3:45 PM" but it only returns "6/20/2015" when I print it to the console or the app.
If this is the case, is there a way I can just extract the time then since I already have the date? Honestly, from the other examples I've seen, they get both. I don't know why I only get the date.
Any help would be greatly appreciated!
You have to set timeStyle as well, e.g.
dateFormatter.dateStyle = .ShortStyle
dateFormatter.timeStyle = .ShortStyle
otherwise you'll get only the "date" part.

Resources