Forcing user not to put previous time on time pickers - ios

I’m using time pickers and they work correctly as expected but the problem that i dont want to user to reserve a past time. when i click on the time pickers they doesn’t allow me to reserve past time but the problem is when i leave it opened and time continues it allow me to choose past time which is the time i click on it for example i opened time picker at 10:11 when i leave time picker opened and its 10:12 it allow me to choose 10:11 which is in past. im planning to show an error massage and force the time pickers to set time at current time if user chooses start time < current time. Hope its clear and this is my code if you can help
func createTimePicker() {
StartTimeTxt.textAlignment = .center
EndTimeTxt.textAlignment = .center
//tool bar
let toolbar = UIToolbar()
toolbar.sizeToFit()
//bar button(
let doneBtn = UIBarButtonItem(barButtonSystemItem: .done, target: nil, action: #selector(donePressed))
toolbar.setItems([doneBtn], animated: true)
//assign tool bar
StartTimeTxt.inputAccessoryView = toolbar
EndTimeTxt.inputAccessoryView = toolbar
// assign time picker to the txt field
StartTimeTxt.inputView = StartTimePicker
EndTimeTxt.inputView = EndTimePicker
let calendar = Calendar.current
//First range
let startTime = Date()
let startRangeEnd = calendar.date(byAdding: DateComponents(minute: 30), to: startTime)!
let startRange = startTime...startRangeEnd
//Second range
let endTime = calendar.date(byAdding: DateComponents(minute: 1), to: startRangeEnd)!
let endRangeEnd = calendar.startOfDay(for: calendar.date(byAdding: DateComponents(day: 1), to: startTime)!)
let endRange = endTime...endRangeEnd
StartTimePicker.date = startTime
StartTimePicker.minimumDate = startTime
StartTimePicker.maximumDate = startRangeEnd
EndTimePicker.date = endTime
EndTimePicker.minimumDate = endTime
EndTimePicker.maximumDate = endRangeEnd
if #available(iOS 13.4, *) {
StartTimePicker.preferredDatePickerStyle = .wheels
EndTimePicker.preferredDatePickerStyle = .wheels
}
}
#objc func donePressed(){
// formatter
let calendar = Calendar.current
let startTime = Date()
let startRangeEnd = calendar.date(byAdding: DateComponents(minute: 30), to: startTime)!
let startRange = startTime...startRangeEnd
//Second range
let endTime = calendar.date(byAdding: DateComponents(minute: 1), to: startRangeEnd)!
let endRangeEnd = calendar.startOfDay(for: calendar.date(byAdding: DateComponents(day: 1), to: startTime)!)
let endRange = endTime...endRangeEnd
let formatter = DateFormatter()
formatter.dateStyle = .none
formatter.timeStyle = .short
StartTimeTxt.text = formatter.string(from: StartTimePicker.date)
self.view.endEditing(true)
EndTimeTxt.text = formatter.string(from: EndTimePicker.date)
self.view.endEditing(true)
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "h:mm a"
startTimer = formatter.string(from: StartTimePicker.date)
endTimer = formatter.string(from: EndTimePicker.date)
// print(start, end)
// Format and print in 12h format
let hourAndMinutes = Calendar.current.dateComponents([.hour, .minute], from: StartTimePicker.date, to: EndTimePicker.date)
print(hourAndMinutes)
// Calculate price, the formula is just an example
var minutesPrice = 0
if ( hourAndMinutes.minute! == 0 ){
minutesPrice = 0
}
else {
minutesPrice = 15
}
let price = hourAndMinutes.hour! * 15 + minutesPrice
TotalPrice.text = String(price) + "SAR"
} ```

Related

My timers shouldn’t be clickable when the minute is done

I’m using time pickers and they work correctly as expected but the problem that i dont want to user to reserve a past time. when i click on the time pickers they doesn’t allow me to reserve past time but the problem is when i leave it opened and time continues it allow me to choose past time which is the time i click on it for example i opened time picker at 10:11 when i leave time picker opened and its 10:12 it allow me to choose 10:11 which is in past. when 10:11 is done it shouldn’t be clickable. Hope its clear and this is my code if you can help
func createTimePicker() {
StartTimeTxt.textAlignment = .center
EndTimeTxt.textAlignment = .center
//tool bar
let toolbar = UIToolbar()
toolbar.sizeToFit()
//bar button(
let doneBtn = UIBarButtonItem(barButtonSystemItem: .done, target: nil, action: #selector(donePressed))
toolbar.setItems([doneBtn], animated: true)
//assign tool bar
StartTimeTxt.inputAccessoryView = toolbar
EndTimeTxt.inputAccessoryView = toolbar
// assign time picker to the txt field
StartTimeTxt.inputView = StartTimePicker
EndTimeTxt.inputView = EndTimePicker
let calendar = Calendar.current
//First range
let startTime = Date()
let startRangeEnd = calendar.date(byAdding: DateComponents(minute: 30), to: startTime)!
let startRange = startTime...startRangeEnd
//Second range
let endTime = calendar.date(byAdding: DateComponents(minute: 1), to: startRangeEnd)!
let endRangeEnd = calendar.startOfDay(for: calendar.date(byAdding: DateComponents(day: 1), to: startTime)!)
let endRange = endTime...endRangeEnd
StartTimePicker.date = startTime
StartTimePicker.minimumDate = startTime
StartTimePicker.maximumDate = startRangeEnd
EndTimePicker.date = endTime
EndTimePicker.minimumDate = endTime
EndTimePicker.maximumDate = endRangeEnd
if #available(iOS 13.4, *) {
StartTimePicker.preferredDatePickerStyle = .wheels
EndTimePicker.preferredDatePickerStyle = .wheels
}
} ```

Storing value of UITextField

I'm using time pickers and I want to store the two values to use them in calculating price, store in firebase.
This is my UI to simplify the idea
The problem is that i don't know which part I can use to store the value of start time and end time (the numbers in UI are written in arabic)
This is my code, can you guide me to the way to store the UITextField values?
#IBOutlet weak var StartTimeTxt: UITextField!
#IBOutlet weak var EndTimeTxt: UITextField!
func createTimePicker() {
StartTimeTxt.textAlignment = .center
EndTimeTxt.textAlignment = .center
//tool bar
let toolbar = UIToolbar()
toolbar.sizeToFit()
//bar button(
let doneBtn = UIBarButtonItem(barButtonSystemItem: .done, target: nil, action: #selector(donePressed))
toolbar.setItems([doneBtn], animated: true)
//assign tool bar
StartTimeTxt.inputAccessoryView = toolbar
EndTimeTxt.inputAccessoryView = toolbar
// assign time picker to the txt field
StartTimeTxt.inputView = StartTimePicker
EndTimeTxt.inputView = EndTimePicker
//time picker mode
/* StartTimePicker.datePickerMode = .time
EndTimePicker.datePickerMode = .time*/
let calendar = Calendar.current
//First range
let startTime = Date()
let startRangeEnd = calendar.date(byAdding: DateComponents(minute: 30), to: startTime)!
let startRange = startTime...startRangeEnd
//Second range
let endTime = calendar.date(byAdding: DateComponents(minute: 1), to: startRangeEnd)!
let endRangeEnd = calendar.startOfDay(for: calendar.date(byAdding: DateComponents(day: 1), to: startTime)!)
let endRange = endTime...endRangeEnd
StartTimePicker.date = startTime
StartTimePicker.minimumDate = startTime
StartTimePicker.maximumDate = startRangeEnd
EndTimePicker.date = endTime
EndTimePicker.minimumDate = endTime
EndTimePicker.maximumDate = endRangeEnd
if #available(iOS 13.4, *) {
StartTimePicker.preferredDatePickerStyle = .wheels
EndTimePicker.preferredDatePickerStyle = .wheels
}
}

How to get the datetime of two hours interval?

I tried several ways, but I didn't get a workable solution.
I need a two hours interval datetime from today to the next five days and the time frame must be morning 7:00 to night 22:00.
What I tried so far is:
let cal = Calendar(identifier: Calendar.Identifier.gregorian)
for i in 1..<6{
let date = Date()
var components = DateComponents()
components.setValue(i, for: .day)
let expirationCal = cal.date(byAdding: components, to: date)
let calendar = NSCalendar.autoupdatingCurrent
for i in 0..<12 {
var newDateTime = calendar.date(byAdding: Calendar.Component.hour, value: 1, to: expirationCal!)
let currentHour = calendar.component(.hour, from: newDateTime!)
let hourInt = Int(currentHour.description)!
if hourInt >= 8 && hourInt <= 22 {
print(newDateTime)
}
}
}
My suggestion:
Calculate start and end date
Enumerate the dates at full hours from start to end date and filter the even dates in the given range
let cal = Calendar(identifier: .gregorian)
let startDate = Date()
let endDate = cal.date(byAdding: .day, value: 5, to: startDate)
let fullHourComponents = DateComponents(minute: 0, second: 0)
var dates = [Date]()
cal.enumerateDates(startingAfter: startDate, matching: fullHourComponents, matchingPolicy: .nextTime) { date, strict, stop in
if let validDate = date {
if validDate == endDate { stop = true; return}
let currentHour = cal.component(.hour, from: validDate)
if currentHour.isMultiple(of: 2), (7..<23) ~= currentHour {
dates.append(validDate)
}
}
}
print(dates)
Consider that the printed dates are in UTC

How to save the disability of a button for Xcode

what i am to do with the button is once it is pressed it will disable for the rest of the day. now my code does disable it once it is pressed but if the user leaves the application and comes back to it, the button will be enabled again. is there a way to use NSUserDefaults?
let save = UserDefaults.standard
let calendar = Calendar.current
let now = Date()
this is in the viewDidLoad:
let seven_today = calendar.date(
bySettingHour: 7,
minute: 0,
second: 0,
of: now)!
let two_thirty_today = calendar.date(
bySettingHour: 14,
minute: 30,
second: 0,
of: now)!
if now >= seven_today && now <= two_thirty_today
{
getPointsOutlet.isEnabled = true
}
else
{
getPointsOutlet.isEnabled = false
}
this is the function of pressing the button:
Total_Points += 12
pointsLabel.text = "Total Points: \(Total_Points)"
getPointsOutlet.isEnabled = false
Try this:
if now >= seven_today && now <= two_thirty_today
{
let savedDayNum = defaults.integer(forKey: "dayClickNum")
let date = Date()
let calendar = Calendar.current
let nowDayNum = calendar.component(.day, from: date)
if(savedDayNum == nowDayNum)
{
getPointsOutlet.isEnabled = false
}
else
{
getPointsOutlet.isEnabled = true
}
}
else
{
getPointsOutlet.isEnabled = false
}
// in function click do this
Total_Points += 12
pointsLabel.text = "Total Points: \(Total_Points)"
getPointsOutlet.isEnabled = false
let date = Date()
let calendar = Calendar.current
let dayOfClickDate = calendar.component(.day, from: date)
defaults.set(dayOfClickDate, forKey: "dayClickNum")
Also for a perfect solution you may take care of month , as app may not be launched again by user for a month that may disable the button if the stored num day is coincidence d with open day of another month

How do I get the age after using a date picker?

I need to get the age after the datepicker has been used. How would I do this. I can currently get the datepicker to work.
#IBAction func datepickerobj(sender: UITextField) {
let datePickerView:UIDatePicker = UIDatePicker()
datePickerView.datePickerMode = UIDatePickerMode.Date
sender.inputView = datePickerView
datePickerView.addTarget(self, action: Selector("datePickerValueChanged:"), forControlEvents: UIControlEvents.ValueChanged)
}
func datePickerValueChanged(sender:UIDatePicker) {
let dateFormatter = NSDateFormatter()
dateFormatter.dateStyle = NSDateFormatterStyle.MediumStyle
dateFormatter.timeStyle = NSDateFormatterStyle.NoStyle
dateofbirth.text = dateFormatter.stringFromDate(sender.date)
let myDOB = NSCalendar.currentCalendar().dateWithEra(1, year: 1970, month: 09, day: 10, hour: 0, minute: 0, second: 0, nanosecond: 0)!
let myAge = myDOB.age
}
Swift 4.1 / Xcode 9.4.1
func age(dateOfBirth: Date) -> Double {
var ageComponents: DateComponents = Calendar.current.dateComponents([.year], from: dateOfBirth, to: Date())
return Double(ageComponents.year!)
}
This will work fine for u
var birthday: NSDate = ..... //date that comes from date picker
var now: NSDate = NSDate()
var ageComponents: NSDateComponents = NSCalendar.currentCalendar().components(.Year, fromDate: birthday, toDate: now, options: 0)
var age: Int = ageComponents.year()
If u want to formate date you can use DateFormatter
Ex.
let usDateFormat = NSDateFormatter.dateFormatFromTemplate("MMddyyyy", options: 0, locale: NSLocale(localeIdentifier: "en-US"))
//usDateFormat now contains an optional string "MM/dd/yyyy".
let gbDateFormat = NSDateFormatter.dateFormatFromTemplate("MMddyyyy", options: 0, locale: NSLocale(localeIdentifier: "en-GB"))
//gbDateFormat now contains an optional string "dd/MM/yyyy"
formatter.dateFormat = usDateFormat
let usSwiftDayString = formatter.stringFromDate(swiftDay)
// usSwiftDayString now contains the string "06/02/2014".
formatter.dateFormat = gbDateFormat
let gbSwiftDayString = formatter.stringFromDate(swiftDay)
// gbSwiftDayString now contains the string "02/06/2014".
//may be it will help for u
let formatter = NSDateFormatter()
formatter.dateFormat = "yyyy"
let currentYear: Int = Int(formatter.stringFromDate(NSDate()))
let dobYear: Int = Int(formatter.stringFromDate(myDOB))
let age: Int = currentYear - dobYear
extension Date {
func age() -> Int {
return Int(Calendar.current.dateComponents([.year], from: self, to: Date()).year!)
}
}
An Date extension version, which let you call the method on any Date var. eg:
let calendar = NSCalendar.currentCalendar()
let components = calendar.components([NSCalendarUnit.Year, NSCalendarUnit.Month, NSCalendarUnit.Day], fromDate: NSDate.init())
components.day = 31
components.month = 1
components.year = 1979
let date = calendar.dateFromComponents(components)
let years = date.age

Resources