You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中如何基于App设置而非设备配置UIDatePicker的12/24小时制

解决UIDatePicker跟随App内12/24小时制设置及日本和历显示问题

要实现UIDatePicker不受系统时间制设置影响、完全遵循App内配置,同时保证日本和历能正常显示「令和」前缀,需要分历法动态配置Picker的Locale、Calendar以及时间周期(hourCycle),而非单纯切换Locale。具体方案如下:

核心思路

  • 公历场景:通过修改Locale的hourCycle属性控制12/24小时制,避免切换Locale导致其他历法异常
  • 日本和历场景:明确指定Picker的calendar为JapaneseCalendar,并使用ja_JP Locale,同时通过hourCycle控制时间制,确保和历前缀正常显示
  • TextField的日期格式化完全遵循App内用户设置的格式,与Picker显示解耦

关键实现代码

import UIKit

class ViewController: UIViewController {

    let dateTextField = UITextField()
    let datePickerContainer = UIView()
    let datePicker = UIDatePicker()
    let toolbar = UIToolbar()

    // 模拟App内用户配置:实际开发中替换为UserDefaults读取逻辑
    var userPrefers24Hour: Bool {
        return true // true=24小时制,false=12小时制
    }
    
    var userPrefersJapaneseCalendar: Bool {
        return false // true=使用日本和历
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        
        setupDateTextField()
        setupDatePickerContainer()
        setupToolbar()
        setupDatePicker()
    }

    // 原setupDateTextField、setupDatePickerContainer、setupToolbar代码保留,此处省略

    func setupDatePicker() {
        datePicker.datePickerMode = .dateAndTime
        datePicker.preferredDatePickerStyle = .inline
        datePicker.translatesAutoresizingMaskIntoConstraints = false
        datePicker.addTarget(self, action: #selector(dateChanged), for: .valueChanged)
        datePickerContainer.addSubview(datePicker)
        
        // 动态配置Picker的Locale、Calendar和时间制
        configureDatePickerLocaleAndCalendar()
        
        // 约束配置
        NSLayoutConstraint.activate([
            datePicker.leadingAnchor.constraint(equalTo: datePickerContainer.leadingAnchor, constant: 10),
            datePicker.trailingAnchor.constraint(equalTo: datePickerContainer.trailingAnchor, constant: -10),
            datePicker.topAnchor.constraint(equalTo: datePickerContainer.topAnchor, constant: 10),
            datePicker.bottomAnchor.constraint(equalTo: toolbar.topAnchor, constant: -10)
        ])
    }

    /// 动态配置UIDatePicker的Locale、Calendar和时间周期
    private func configureDatePickerLocaleAndCalendar() {
        var locale: Locale
        var calendar: Calendar
        
        if userPrefersJapaneseCalendar {
            // 日本和历场景:指定ja_JP Locale和JapaneseCalendar
            locale = Locale(identifier: "ja_JP")
            calendar = Calendar(identifier: .japanese)
        } else {
            // 公历场景:使用en_POSIX作为基础Locale,避免系统区域干扰
            locale = Locale(identifier: "en_POSIX")
            calendar = Calendar(identifier: .gregorian)
        }
        
        // 根据用户设置修改Locale的时间周期
        locale = locale.withHourCycle(userPrefers24Hour ? .h24 : .h12)
        
        datePicker.locale = locale
        datePicker.calendar = calendar
    }

    @objc func dateChanged() {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = getUserPreferredDateFormat()
        
        // 日本和历时同步修改Formatter的Calendar,保证输出格式正确
        if userPrefersJapaneseCalendar {
            dateFormatter.calendar = Calendar(identifier: .japanese)
        }
        
        dateTextField.text = dateFormatter.string(from: datePicker.date)
    }

    // 原showDatePicker、doneButtonTapped代码保留,此处省略

    func getUserPreferredDateFormat() -> String {
        // 根据用户时间制返回对应格式
        return userPrefers24Hour ? "dd/MM/yyyy HH:mm" : "dd/MM/yyyy hh:mm a"
    }
}

// 扩展Locale,简化时间周期设置
extension Locale {
    func withHourCycle(_ hourCycle: HourCycle) -> Locale {
        var components = self.languageComponents
        components.hourCycle = hourCycle.rawValue
        return Locale(languageComponents: components)
    }
    
    enum HourCycle: String {
        case h12 = "h12"
        case h24 = "h24"
    }
}

代码说明

  1. 用户配置模拟:userPrefers24Hour和userPrefersJapaneseCalendar模拟从UserDefaults读取的真实配置,实际开发中替换为对应逻辑即可
  2. Locale扩展:封装了修改Locale时间周期的逻辑,iOS 13+支持该属性,无需切换整个Locale就能控制时间显示格式
  3. Picker动态配置:
    • 日本和历时强制使用JapaneseCalendar和ja_JP Locale,确保Picker显示「令和」等和历前缀
    • 公历场景使用en_POSIX作为基础Locale,避免系统区域设置干扰,同时通过hourCycle精准控制时间制
  4. 日期格式化:TextField显示严格遵循用户设置的格式,日本和历时同步修改Formatter的Calendar,保证输出格式与Picker显示一致

内容的提问来源于stack exchange,提问作者AJITHKUMAR

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 02:06:02