(Swift) Setting UIDatePicker View from User Input - ios

First I display a UIDatePicker on the screen and allow the user to choose a date and time. I save that value like this, which gets a date format that looks like this: 6/1/16, 1:47 PM
let time = NSDateFormatter.localizedStringFromDate(datePicker.date, dateStyle: .ShortStyle, timeStyle: .ShortStyle)
Later on in the application, I want users to be able to edit their original date, so when a button is pressed, I would like the UIDatePicker to display the time that they had originally chosen.
I am using the following code to try to make that happen, although the app keeps getting a runtime error because the date is always nil.
let dateFromatter = NSDateFormatter()
let date = dateFromatter.dateFromString("6/1/16, 1:47 PM")
datePicker.setDate(date!, animated: true)
Thank you for your help!

You are having an issue with the date format and not with the date picker.
#IBOutlet weak var datePicker: UIDatePicker!
override func viewDidLoad() {
super.viewDidLoad()
let dateFromatter = NSDateFormatter()
dateFromatter.dateFormat = "M/d/yy, H:mm"
if let date = dateFromatter.dateFromString("6/1/16, 1:47") {
datePicker.setDate(date, animated: true)
}
}

For a short style string use below format:
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "M/d/yy, H:mm"
dateFormatter.stringFromDate(NSDate())

Related

How to get DatePicker time to Calendar component and insert to Label component in Swift

I am new in this forum but it helped me a lot in coding.
Currently I am trying to code an iOS App as a time calculator in Swift (Xcode 11.2.1)
It should be able to pick a time from the DatePicker component and add 8 hours worktime to it.
So the function is to display the time you can leave your workplace without getting negative in your flextime.
It should be displayed in the Label component.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var dateLabel: UILabel!
#IBOutlet weak var datePicker: UIDatePicker!
#IBAction func datePickerChanged(_ sender: Any) {
let dateFormatter = DateFormatter()
dateFormatter.timeStyle = DateFormatter.Style.short //show time in h:mm format
dateFormatter.locale = Locale(identifier: "de-DE") //locale Germany
let endTime = dateFormatter.date // declaring as date
let calendar = Calendar.date(from: endTime) // get time from UIDatePicker
let addHours = Calendar.date(byAdding: .hour, value: 8, to: endTime) // add 8 hours
let endTimeString = dateFormatter.string(from: endTime) //convert time from date to String
dateLabel.text = endTimeString // show calculated time in UILabel
}
}
I am getting 3 errors.
In the first let calendar line it says:
Instance member 'date' cannot be used on type 'Calendar'; did you mean to use a value of this type instead?
In the following let addHours line I am getting the same error again, what is the point here?
The last error starts at the line when I am trying to convert the time from type date to String.
Cannot convert value of type '(String) -> Date?' to expected argument type 'Date'
Anyone could help me?
I think you want something like this:
#IBAction func datePickerChanged(_ sender: UIDatePicker) {
var pickerDate = sender.date
let calendar = Calendar.current
guard let endDate = calendar.date(byAdding: .hour, value: 8, to: pickerDate) else { return }
let dateFormatter = DateFormatter()
dateFormatter.timeStyle = DateFormatter.Style.short //show time in h:mm format
dateFormatter.locale = Locale(identifier: "de-DE") //locale Germany
var endTimeString = dateFormatter.string(from: endDate) //convert time from date to String
dateLabel.text = endTimeString // show calculated time in UILabel
}
First, you need to get the selected date from the UIDatePicker.
Then, for date calulations, you need to specify a calendar to work with. Typically the current calendar is what you want (this is the calendar specified for the device). Then, add 8 hours and convert it to a string.
Btw.: you need to keep in mind that when the user picks a date in the evening, there is a "day flip" when you add 8 hours.
Update
To add somthing like 8 hours and 13 minutes, it's best to use DateComponents:
var now = Date()
var calendar = Calendar.current
var addComp = DateComponents(calendar:calendar,
hour:8,
minute:13)
if let then = calendar.date(byAdding: addComp, to: now, wrappingComponents:false) {
print(now)
print(then!)
}

Set time also on a textfield after setting the date

I'm setting a date on my text field like so...
override func viewDidLoad() {
super.viewDidLoad()
showDatePicker()
}
func showDatePicker() {
datePickerStartDate.datePickerMode = .date
datePickerStartDate.addTarget(self, action: #selector(EventDetailViewController.startDatePickerSelect(sender:)), for: .valueChanged)
startDateTextfield.inputView = datePickerStartDate
}
#objc func startDatePickerSelect(sender: UIDatePicker) {
let formatter = DateFormatter()
formatter.dateStyle = .medium
startDateTextfield.text = formatter.string(from: sender.date)
}
This opens a datepicker on tap on the textfield and sets the date. But what I want is after I select the date, I want the time picker also to show up so that I can set the time also. And this time should get appended to the date that was set initially. How can I achieve that..?
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "hh:mm"
You can get the time of your choice from the string as :
let timeStr = "2:00"
var time = dateFormatter.dateFromString(timeStr)
Or you can add and subtract specific time from the current date as :
//It will give you the time by adding 5 minutes to the current time you can use (-5*60) to get the time 5 minute back.
var date = Date().addingTimeInterval(TimeInterval(5*60))
var timeStr = dateFormatter.string(from: date)

match datePicker date and timer with users Date and Time (swift3)

My code below creates a date picker and has it select a date and time. All I want to do is when the date picker's date and time match the user's phone's date and time is to print the line "cool". That's it. I commented the line that is causing me problems.
import UIKit
var dateFormatter : DateFormatter!
let datePicker2 = UIDatePicker();
let date = Date()
class ViewController: UIViewController {
#IBOutlet var dateLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
let datePicker : UIDatePicker = UIDatePicker(frame: CGRect(x: 0,y: 330,width: self.view.frame.size.width,height: 220))
datePicker.datePickerMode = UIDatePickerMode.dateAndTime
self.view.addSubview(datePicker)
datePicker.addTarget(self, action: #selector(ViewController.change(_:)), for: UIControlEvents.valueChanged)
dateFormatter = DateFormatter()
dateFormatter.dateFormat = "YYYY-MM-dd hh:mm"
}
#IBAction func change(_ sender : UIDatePicker)
{
dateLabel.text = dateFormatter.string(from: sender.date)
///print cool line; what I have does not work
if dateLabel.text == String(describing: date){
print("cool")
}
}
}
Your primary issue is how you compare the two dates. You should be using the same date formatter to convert both Date instances to strings in the same format. Then you can compare the two strings.
#IBAction func change(_ sender : UIDatePicker)
{
let pickerString = dateFormatter.string(from: sender.date)
let nowString = dateFormatter.string(from: Date())
dateLabel.text = pickerString
if pickerString == nowString {
print("cool")
}
}
You are also using the wrong format. You need "yyyy-MM-dd HH:mm". YYYY is slightly different. You always want yyyy unless you have a clearly understood and specific need to use YYYY. And for the hour you want HH instead of hh. HH is a 24-hour hour while hh is a 12-hour hour. Only use hh is you also use a (for AM/PM).
And your properties should be inside the class, not outside.
Move datePicker2 inside the class.
date is now obsolete based on my answer so you can remove it completely.
dateFormatter should also be moved inside the class.

Saving Date and time in Parse backend

I have searched Parse blog to see if I can get the solution to this, but didn't get any satisfactory answer. So I though I will clearly ask the question here with all the details so anyone else stuck at similar situation will find it easy to work.
Need:
I have a departure and return text field which are updated using a single UIDatePicker. I want to save the selected dates in my Parse.com database. To which I can query and filter data. I also want to store local timezone in parse if possible. I am working with checking number of days but it was not relevant to this question so not including the code for that.
Success & Problem:
I am able to save correct date and time in String format , but when I try to save in NSDate format using the code below, I get wrong time.
For ex: my date selection and stored result in parse are as below:
Departure date:
Date Picker selection: 01/May/2015 01:00 AM +0530
Stored date in Parse: Apr 30, 2015, 19:30
Return Date:
Date Picker selection: 02/May/2015 01:00 AM +0530
Stored date in Parse: May 01, 2015, 19:30
//My code is as below:
#IBOutlet var dOfTravelText: UITextField!
#IBOutlet var returnDateText: UITextField!
lazy var dateFormatter: NSDateFormatter = {
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "dd/MMM/yyyy hh:mm a Z"
// dateFormatter.dateStyle = .MediumStyle
// dateFormatter.timeStyle = .ShortStyle
return dateFormatter
}()
#IBAction func travelDatePicker(sender: UITextField) {
datePickerView.minimumDate = NSDate()
datePickerView.datePickerMode = UIDatePickerMode.DateAndTime
sender.inputView = datePickerView
timeSelected = sender
datePickerView.addTarget(self, action: "handleDatePicker:", forControlEvents: UIControlEvents.AllEvents)
}
// Date Picker target - Displaying date in textfield
func handleDatePicker(sender: UIDatePicker) {
//var dateFormatter = NSDateFormatter()
//dateFormatter.dateFormat = "mm/dd/yyyy"
timeSelected.text = dateFormatter.stringFromDate(sender.date)
println("From Date \(dOfTravelText.text!)")
println("To Date \(returnDateText.text!)")
}
// Submitting the dates to parse backend
#IBAction func postBtn(sender: AnyObject) {
let date = NSDate()
let calendar = NSCalendar.currentCalendar()
let components = calendar.components(.CalendarUnitHour | .CalendarUnitMinute, fromDate: date)
let dateMakerFormatter = NSDateFormatter()
dateMakerFormatter.dateFormat = "dd/MMM/yyyy hh:mm a Z"
let dD = dateMakerFormatter.dateFromString("\(dOfTravelText.text!)")!
let departureD = NSDateFormatter.localizedStringFromDate(dD, dateStyle: .MediumStyle, timeStyle: .ShortStyle)
println("From-------...\(departureD)")
let rD = dateMakerFormatter.dateFromString("\(returnDateText.text!)")!
let returnD = NSDateFormatter.localizedStringFromDate(rD, dateStyle: .MediumStyle, timeStyle: .ShortStyle)
println("To-------\(returnD)")
var userPost = PFObject(className:"UserPost")
userPost["departureDate"] = dD // Works but has Wrong time
userPost["rDate"] = rD // Works but Wrong time
userPost["travelDate"] = dOfTravelText.text // Works but it is stored in String format
userPost["returnDate"] = returnDateText.text // Works but it is stored in string format
userPost.saveInBackgroundWithBlock {
(success, error: NSError?) -> Void in
if (success) {
// The object has been saved.
println("Saved")
} else {
// There was a problem, check error.description
println("Error")
}
}
}
}
// Parse database column and type
travelDate & returnDate are defined as of type "String"
departureDate & rDate are defined as Of type "Date"
Just for information: I am using
Platform - iOS Swift (xcode 6.3, swift 1.2)
Database backend = Parse.com
Since Parse stores the dates referenced to GMT, when you check them on parse or retrieve them, you may find this difference to your local timezone. In general dates are stored in GMT.
You can add an extra field in your Parse database and store the local timezone there. When retrieving data you can then use that information to interpret the date in the zone it is referenced in.
Depending on the type of data you store it might be okay to always interpret the date in the users local timezone, even when this has changed. You also could ask the user for a resolution if saved timezone and user timezone are different (so the user has moved).
Setting up date pickers:
#IBOutlet weak var dDDatePicker: UIDatePicker!
#IBOutlet weak var rdDatePicker: UIDatePicker!
override func viewDidLoad() {
super.viewDidLoad()
setUpDatePickers()
}
func setUpDatePickers() {
// Set start date
dDDatePicker.date = Date()
rdDatePicker.date = Date()
// Set min and max date if you want
dDDatePicker.maximumDate = minDepartDate
rdDatePicker.maximumDate = minReturnDate
dDDatePicker.minimumDate = maxDepartDate
rdDatePicker.minimumDate = maxReturnDate
}
Saving dates to Parse:
func saveUserPost() {
let dD = dDDatePicker.date
let rd = rdDatePicker.date
let userPost = PFObject(className: "UserPost")
userPost["departureDate"] = dD
userPost["rDate"] = rD
userPost.saveInBackgroundWithBlock {
(success, error) -> Void in
if (success) {
// The object has been saved.
print("Saved")
} else {
// There was a problem, check error.description
print("Error")
}
}
}
As mentioned date is saved in UTC I would use DateFormatter() to get it back to string in the correct time zone:
if let dD = userPost["departureDate"] as? Date {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let str = dateFormatter.string(from: dD)
print("Depart date \(str)")
}
if let rD = userPost["rDate"] as? Date {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let str = dateFormatter.string(from: rD)
print("Return date \(str)")
}
Use this link to set 'dateFormat' however you want:
https://nsdateformatter.com/
From my understanding dateFormatter will format to the devices current timeZone - Honestly I never tested it in different time zones but it works for EST - you can test and if not as mentioned you can also save the user time zone and then specify in date formatter like so
dateFormatter.timeZone = TimeZone(abbreviation: "\(usertimeZone)")
Hope this helps!

Information about current date as Label

I've problems with NSDate. It's simple to write the current date in "println". How I could put my current date as a Label? This is my code:
var timer = NSTimer()
override func viewDidLoad() {
super.viewDidLoad()
timer = NSTimer.scheduledTimerWithTimeInterval(1,target:self, selector: Selector("update"),userInfo: nil, repeats :true)
let date = NSDate()
println(NSDate)
}
let formatter = NSDateFormatter
formatter.dateFormat = "yyyy-MM-dd" // Set the way the date should be displayed
someLabel.text = formatter.stringFromDate(someDate)
See Date Formatting Guide
for more info on "yyyy-MM-dd" possibilities

Resources