Error when user enters time from keyboard - ios

User enters time from keyboard. I have limited the keyboard so that the user can only type in the correct time. But still jumps into the else case from time to time (although when checking the input times are still correct). My app has users from many countries so I think there is a problem here.
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "hhmma"
dateFormatter.amSymbol = "AM"
dateFormatter.pmSymbol = "PM"
var AMorPMStart = ""
if startTimeAMPMSegment.selectedSegmentIndex == 1 {
AMorPMStart = "PM"
}else {
AMorPMStart = "AM"
}
var startDate = Date()
if let _ = dateFormatter.date(from: startDateHourString + startDateMinuteString + AMorPMStart) {
startDate = dateFormatter.date(from: startDateHourString + startDateMinuteString + AMorPMStart)!
}else {
AlertService.showInfoAlert(in: self, title: StringForLocal.error, message: StringForLocal.invalidStartTime)
return
}
I have tested a lot of time input cases but it seems to be wrong only for certain set of users. On my device everything is fine.

Related

Date formatting for next available date in Swift [duplicate]

This question already has answers here:
Convert string with unknown format (any format) to date
(2 answers)
Closed 5 years ago.
I'm currently downloading fixture lists for a sports app from a third party website that runs the league, so the data I have to work with is restricted.
I'm trying to implement a feature that displays the next upcoming fixture.
My problem is the dates being retrieved look like this:
"Sat 9th Sep 17" and "Sat 24th Mar 18" for example.
I've tried numerous date formats in the DateFormatter that I know of and can't find anything that uses this specific format.
If I try to use the Date from string method in the date formatter with one of the above strings I get a nil value.
I have an array of fixtures, each with their own dates. I need to compare each of these to the current date to figure out which is next in line.
My temporary fix for this was just to loop through the fixtures and as soon as one did not have a result to display that as the next fixture. Obviously this doesn't work when a game may not have been played for whatever reason.
What would be the best way to deal with this?
Basically you would just need to convert the current date to the same format as the date you get from your third party website (or the opposite) so you can compare them easily:
let currentDate = Date()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "EE MMM"
let firstPartStringDate = dateFormatter.string(from: currentDate)
dateFormatter.dateFormat = "yy"
let lastPartStringDate = dateFormatter.string(from: currentDate)
let day = Calendar.current.component(.day, from: currentDate)
let formatter = NumberFormatter()
formatter.numberStyle = .ordinal
guard let ordinalDay = formatter.string(for: day) else {
return
}
let finalDateString = firstPartStringDate + " \(ordinalDay) " + lastPartStringDate
print(finalDateString)
And for today's current date you would get the exactly same format as the one you get from the third-party website :
Sun Sep 17th 17
UPDATE: Here is how you could convert the String you get from the third-party website to a Date, and then compare it with the current date. This solves the problem of having the st, nd, rd and th inside the String at first.
// This is the string you get from the website
var webDateString = "Sat 9th Sep 17"
// First, remove the st, nd, rd or th if it exists :
if let stSubrange = webDateString.range(of:"st") {
webDateString.removeSubrange(stSubrange)
} else if let ndSubrange = webDateString.range(of:"nd") {
webDateString.removeSubrange(ndSubrange)
} else if let rdSubrange = webDateString.range(of:"rd") {
webDateString.removeSubrange(rdSubrange)
} else if let thSubrange = webDateString.range(of:"th") {
webDateString.removeSubrange(thSubrange)
}
// Now convert the string to a date :
dateFormatter.dateFormat = "EE MMM dd yy"
guard let formattedDate = dateFormatter.date(from: finalDateString) else {
return
}
// You can now compare formattedDate and the current date easily like so :
let currentDate = Date()
if formattedDate < currentDate {
// Do something interesting here :)
} else {
// Do something else!
}

getting wrong time while set date and time in one nsdate separately in ios

when i'm going set event from app to device calendar. i got wrong time.
i have three date picker one for date and other two for start time and end time for event. i set start date as end date in EKEvent because i have to set event on that day only.
get date from date-picker and store it as startdate and end date as nsdate type. below is my date-picker method
func pickerDate()
{
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "YYYY-MM-dd"
routineStartDate = dateFormatter.string(from: self.startDatePicker.date)
// it is for database entry in string and i get right string
print(routineStartDate)
startDate = self.startDatePicker.date as NSDate
print(startDate)
endDate = startDate
}
below method is for start time where i get time and convert to Time Interval and set it to start date.
func starttime() {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "HH:mm"
let then: Date? = self.startTimePicker.date
let difference: TimeInterval? = then?.timeIntervalSinceNow
startDate.addingTimeInterval(difference!)
routineStartTime = dateFormatter.string(from: self.startTimePicker.date)
// it is for database entry in string and i get right string
print(routineStartTime)
}
below method is for end time where i get time from picker and convert to Time Interval and set Time Interval to enddate
func endtime() {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "HH:mm"
routineEndTime = dateFormatter.string(from: self.endTimePicker.date)
print(routineEndTime)
// it is for database entry in string and i get right string
let then: Date? = self.endTimePicker.date
let difference: TimeInterval? = then?.timeIntervalSinceNow
endDate.addingTimeInterval(difference!)
}
below image showing which date i set in picker
below is My EKEvent method where i create event.
existevent.title = tempDescription
existevent.startDate = startDate as Date
existevent.endDate = endDate as Date
existevent.isAllDay = false
existevent.notes = "This is a note"
existevent.calendar = cal
when i check event in calendar i got Problem, i get wrong time in event.i set start time 12:50 pm end time 1:50 pm on date 27 june 2017 in caledar app. date is set perfectly but why time is not set perfectly ? below image for calendar app.
i have doubt in conversion of time interval and set to date. but what i missing dont know.
please suggest me solution and ideas to solve.
Thank you
you need to convert the time to the desired time zone. Because now the date is set correctly in your timezone, but is displayed in +0000 Screenshot. Use calendar for date representation this
And change your code like this in both methods:
startDate.addingTimeInterval(difference!)
to
self.startDate = startDate.addingTimeInterval(difference!)
and
endDate.addingTimeInterval(difference!)
to
self.endDate = endDate.addingTimeInterval(difference!)
in your case Xcode Warning "Result of call to 'addingTimeInterval' is unused"
Try to convert date, before set it to you "existevent", or when you show it
func convertDate(date:Date) -> Date {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "HH:mm" // or other format
var comp = DateComponents()
let calendar = Calendar.current
comp.hour = Calendar.current.component(.hour, from: date)
comp.minute = Calendar.current.component(.minute, from: date)
comp.timeZone = TimeZone(abbreviation: "GMT")!
return calendar.date(from: comp)!
}

Method works on emulator but crashes on device. Swift 2.2

I'm trying to create a method that will return the amount of time that has passed since a request was made. This method takes in one parameter called requestTime. Since the time can be in both 24hr ex: "08/25/16, 14:34" or 12hr ex: "08/25/16, 2:34 PM" the method takes into account all these variables and handles them properly. Now here is the problem: this method works on Playgound, and on the emulator, but not when I run it on my device. (See pictures below)
func calculateTimeSinceRequestWasMade(requestTime:String) -> String{
//Empty variable for 24 hour format
var dateIn24HrFormat = ""
if(requestTime.containsString("AM") || requestTime.containsString("PM")){
//If request time was in 12 hr format we convert it into 24hr
let dateFormatter1 = NSDateFormatter()
dateFormatter1.dateFormat = "MM/dd/yy, h:mm a"
let date = dateFormatter1.dateFromString(requestTime)
dateFormatter1.dateFormat = "MM/dd/yy, HH:mm"
dateIn24HrFormat = dateFormatter1.stringFromDate(date!)
}else{
//If it was already 24hr we just assign it to our 24hr variable
dateIn24HrFormat = requestTime
}
//Create a time object of the current date in the desired format
let today = NSDate()
let formatter = NSDateFormatter()
formatter.dateFormat = "MM/dd/yy, HH:mm"
let currentFormattedTime = formatter.stringFromDate(today)
//Create a formatter
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "MM/dd/yy, HH:mm"
let dateAsString = dateIn24HrFormat
//Assign both variable with nice names
let postTime = dateFormatter.dateFromString(dateAsString)
let currentTime = dateFormatter.dateFromString(currentFormattedTime)
//Compare the time of both posts and the results is divided by 60, so the result is in minutes
let timeSincePost = (currentTime!.timeIntervalSinceDate(postTime!)/60)
if(timeSincePost < 60){
return ("\(Int(timeSincePost))m")
}else{
return ("\(Int(timeSincePost/60))h")
}
}
As you can see, in this playground file the method works for both 24hr and 12hr formats. Both method calls returned "6h" meaning that the post was made 6 hours ago.
HOWEVER, whenever I run this method on my device it simply doesn't work. It crashes as it forcefully unwraps an nil. If I run this on the built in emulator, it works, but whenever I run it in my actual device it doesn't.
This is the weirdest bug that I have encountered... The Device that I'm running this in is an iPhone 5s running 9.0.2. Please help me if you can!

Toggle a stored flag on a weekly basis

I have a value I would like to switch to another once a week either in the background on when the user launches the app on whichever day even if it's more than a week later. As the user uses the app during the week, each day turns a value e.g. variable b to false but every once a week I want to change that variable back to true for any day that it's been turned to false. I have a function I tried putting in the AppDelegate's didFinishLaunchingWithOptions but I am not precisely sure how to do the check and hence it didn't work. This is my attempt:
func resetOnSunday() {
let date = NSDate()
let formatter = NSDateFormatter()
let timeFormatter = NSDateFormatter()
formatter.dateFormat = "EEEE"
let WeekDay = formatter.stringFromDate(date)
timeFormatter.dateFormat = "HH:mm a"
let time = timeFormatter.stringFromDate(date)
if time >= "00:00 AM" && time <= "00:02 AM" && WeekDay == "Sunday" {
var b = true
}
}
Does anyone know how it can be done?
First of all, you can significantly cut down your code (and make it a lot more reliable) by using NSCalendar.
let date = NSDate()
let calendar = NSCalendar.currentCalendar()
//This will return a NSDate optional which you can check against.
let nextSunday = calendar.nextDateAfterDate(date, matchingUnit: .Weekday, value: 1, options: .MatchNextTime)
if date.timeIntervalSinceDate(nextSunday!) > 0 {
//Do your stuff here
}
Note that:
Weekday units are the numbers 1 through n, where n is the number of days in the week. For example, in the Gregorian calendar, n is 7 and Sunday is represented by 1.
Next, I would use NSUserDefaults for your value:
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setBool(true, forKey: "yourVar")
//Then to read it
defaults.boolForKey("yourVar")

Stuck with creating an event and formatting dates (Swift - EventKit - OS X)

I have been stuck on trying to hardcode a new event. My difficulty lies especially with the dates and formatting
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "MM'/dd'/YYYY"
var dateString = "07/16/2015"
var startDate = dateFormatter.dateFromString(dateString)
var endDate = dateFormatter.dateFromString(dateString)
var newEvent : EKEvent = EKEvent(eventStore: store)
var error : NSError? = nil
newEvent.title = "physiotherapy"
newEvent.location = "London"
newEvent.startDate = startDate
newEvent.endDate = endDate
newEvent.notes = "testing the event"
self.store.saveEvent(newEvent, span: EKSpanThisEvent, commit: true, error: nil)
1) Some assistance as to how I achieve this correctly would be greatly appreciated
2) Also, how can I reference the calendar to use?
Thanks,
dateString doesn't match the format you specified. Why not use the built-in short style?
This appears to work:
let dateFormatter = NSDateFormatter()
dateFormatter.dateStyle = .ShortStyle
var dateString = "07/16/2015"
var startDate = dateFormatter.dateFromString(dateString)
var endDate = dateFormatter.dateFromString(dateString)
startDate and endDate are optionals, so you'll have to unwrap them. In this example, I'm using the force-unwrap operator:
newEvent.startDate = startDate!
newEvent.endDate = endDate!
However, if the input data isn't guaranteed to produce a valid NSDate, you should unwrap the optionals normally and handle the error case.
For year use use "yyyy", not "YYYY" for the year.
"Y" means year of "Week of Year"
See: ICU Formatting Dates and Times

Resources