5

I'm struggling to set the datepicker to only allow time and a 24 hour format in Swift, any ideas how to do this?

Thanks

Prateek
  • 1,724
  • 3
  • 15
  • 27
  • How would you have done it in Objective-C? What have you tried in Swift? – Grimxn Jul 09 '14 at 12:02
  • I have been using the method shown in this post http://stackoverflow.com/questions/2140388/how-to-disable-am-pm-in-uidatepicker Not sure how to carry that to Swift – Prateek Jul 09 '14 at 12:10

3 Answers3

7

The OP says he is trying to recreate this answer in Swift. That answer is a kludge (it depends on Danish locale using 24-hour format, not on actually solving the problem), but here's how you would do that in Swift:

var datePicker = UIDatePicker() // Although you probably have an IBOutlet
datePicker.datePickerMode = UIDatePickerMode.Time
datePicker.locale = NSLocale(localeIdentifier: "da_DK")

but this is a kludge - roll your own UIPicker!

UPDATE The OP said that rolling your own is "hassle" - it's actually really easy - here's one simple way to do it (though a better way would be to subclass UIPickerView)...

import UIKit

class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {

    @IBOutlet weak var myDatePicker: UIPickerView!
    private var calendar = Calendar.autoupdatingCurrent

    override func viewDidLoad() {
        super.viewDidLoad()
        self.time = Date() // updates the picker to "now"
    }

    // MARK: UIPickerViewDataSource
    func numberOfComponents(in: UIPickerView) -> Int { return 2 }
    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        if component == 0 { // Hours
            return 24
        }
        return 12 // five minute intervals
    }

    // MARK: UIPickerViewDelegate
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        if component == 0 { // Hours
            return String(format: "%02d", row)
        }
        return String(format: "%02d", row * 5)
    }
    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        print("picker changed, selected \(self.time)")
    }

    // MARK: Getting & setting the time
    var time: Date {
        get {
            let unitFlags: Calendar.Unit = [.year, .day, .hour, .minute, .second]
            var components = self.calendar.components(unitFlags, from: Date())
            components.hour = self.myDatePicker.selectedRow(inComponent: 0)
            components.minute = self.myDatePicker.selectedRow(inComponent: 1) * 5
            components.second = 0
            if let date = self.calendar.date(from: components) {
                return date
            }
            return Date() // shouldn't get here
        }
        set {
            var components = self.calendar.components([.hour, .minute], from: newValue)
            if let hour = components.hour, let minute = components.minute {
                self.myDatePicker.selectRow(hour, inComponent: 0, animated: true)
                self.myDatePicker.selectRow(minute / 5, inComponent: 1, animated: true)
            }
        }
    }
}
Community
  • 1
  • 1
Grimxn
  • 22,115
  • 10
  • 72
  • 85
  • So how would I go about solving the problem and achieving a 24 hour format? Thanks for this by the way – Prateek Jul 09 '14 at 12:25
  • As one of the answers in that other question said, by rolling your own `UIPicker`. – Grimxn Jul 09 '14 at 12:27
  • Hmm I see, but this workaround would not apply to all timezones? Won't the 24-hour format just be the same? – Prateek Jul 09 '14 at 12:28
  • Yes, it will work (until Denmark adopt a different standard time format!) – Grimxn Jul 09 '14 at 12:30
  • Haha I should hope not! Great! And it would still work if the user has their phone set to 12 hour? I don't want to go to the hassle of creating a custom UIPickerView if this is doing the job I need? – Prateek Jul 09 '14 at 12:33
  • Doing this will override the user locale settings for this control only. But it is this kind of kludge that caused so much heartache in Y2K! – Grimxn Jul 09 '14 at 12:35
  • 1
    In that case I should be safe for a while! Thanks! – Prateek Jul 09 '14 at 12:41
6

IOS Swift4

    let datePickerView: UIDatePicker = UIDatePicker()
    // For 12 hours Format
    datePickerView.locale = Locale(identifier: "en_US")
    // For 24 Hrs
    datePickerView.locale = Locale(identifier: "en_GB")
Maulik Patel
  • 2,045
  • 17
  • 24
1

This is how you do the same in a View using the same hack described above.

import SwiftUI

struct ContentView: View {
    @State var time: Date = Date()
    var body: some View {
        VStack {
            DatePicker("Start Time", selection: $time, displayedComponents: .hourAndMinute)
                .labelsHidden()
                //Trick the Hour picker to show 24-hr format
                .environment(\.locale, Locale(identifier: "en_DK"))
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
JPortillo
  • 543
  • 3
  • 9