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

Swift实现:判断当前时间是否处于跨午夜的营业时间范围内

判断餐厅当前是否营业(Swift实现,支持跨午夜)

Got it,这个需求我之前帮不少开发者处理过,跨午夜的场景确实是最容易踩坑的点,咱们一步步把它搞定。

第一步:先把JSON数据映射成Swift模型

首先得把REST返回的营业时间数据转成Swift能直接用的结构体,用Codable来解析最省心:

struct BusinessHour: Codable {
    let weekday: Int // 这里注意:你的API定义0=周日、1=周一…6=周六,后面要对应Calendar的规则调整
    let openingAt: String // 格式为"HH:mm:ss"
    let closingAt: String // 格式为"HH:mm:ss"
}

第二步:核心判断逻辑(重点处理跨午夜)

接下来写核心的判断函数,关键是区分两种场景:正常时段(关门时间晚于开门时间)和跨午夜时段(关门时间早于开门时间,比如到次日凌晨00:45):

import Foundation

extension BusinessHour {
    // 检查当前时间是否在本时段内
    func isCurrentTimeInRange() -> Bool {
        let calendar = Calendar.current
        let now = Date()
        // Calendar里的weekday规则是1=周日、2=周一…7=周六,和API的0-6对应需要转换
        let currentCalendarWeekday = calendar.component(.weekday, from: now)
        let mappedWeekday = weekday + 1 // 把API的0→1(周日)、1→2(周一)…以此类推
        
        // 先判断是不是今天的营业时间,不是直接返回false
        guard mappedWeekday == currentCalendarWeekday else {
            return false
        }
        
        // 把字符串时间转成可比较的时分秒组件
        let timeFormatter = DateFormatter()
        timeFormatter.dateFormat = "HH:mm:ss"
        timeFormatter.timeZone = calendar.timeZone // 用当前时区,避免时间偏移
        
        guard let openingDate = timeFormatter.date(from: openingAt),
              let closingDate = timeFormatter.date(from: closingAt) else {
            // 时间格式解析失败,返回false
            return false
        }
        
        let openingComponents = calendar.dateComponents([.hour, .minute, .second], from: openingDate)
        let closingComponents = calendar.dateComponents([.hour, .minute, .second], from: closingDate)
        let currentComponents = calendar.dateComponents([.hour, .minute, .second], from: now)
        
        // 分两种情况处理
        if closingDate > openingDate {
            // 正常时段:比如07:30到23:00,只要当前时间在两者之间
            return currentComponents >= openingComponents && currentComponents <= closingComponents
        } else {
            // 跨午夜时段:比如07:30到00:45,当前时间≥07:30(当天) 或者 ≤00:45(次日凌晨)
            return currentComponents >= openingComponents || currentComponents <= closingComponents
        }
    }
}

// 给数组加个扩展,批量检查所有营业时间
extension Array where Element == BusinessHour {
    func isRestaurantOpenNow() -> Bool {
        return contains { $0.isCurrentTimeInRange() }
    }
}

第三步:实际使用示例

假设你已经从接口拿到了营业时间数组,直接调用就行:

// 用你提供的示例数据测试
let sampleBusinessHours: [BusinessHour] = [
    BusinessHour(weekday: 0, openingAt: "07:30:00", closingAt: "00:45:00"),
    BusinessHour(weekday: 1, openingAt: "07:30:00", closingAt: "23:00:00"),
    BusinessHour(weekday: 2, openingAt: "07:30:00", closingAt: "23:00:00"),
    BusinessHour(weekday: 3, openingAt: "07:30:00", closingAt: "23:00:00"),
    BusinessHour(weekday: 4, openingAt: "07:30:00", closingAt: "23:00:00"),
    BusinessHour(weekday: 5, openingAt: "07:30:00", closingAt: "23:00:00"),
    BusinessHour(weekday: 6, openingAt: "07:30:00", closingAt: "00:45:00")
]

// 判断当前是否营业
let isOpen = sampleBusinessHours.isRestaurantOpenNow()
print("餐厅当前是否营业:\(isOpen ? "是" : "否")")

几个要注意的细节

  • 时区问题:如果餐厅在固定时区营业,记得把timeFormatter.timeZone改成餐厅所在时区(比如TimeZone(identifier: "Asia/Shanghai")),避免用户跨时区时判断错误。
  • Weekday映射:不同API的weekday定义可能不一样(比如有的0=周一),一定要根据实际接口文档调整mappedWeekday的计算逻辑。
  • 时间格式兼容:如果接口返回的时间格式有变化(比如不带秒),记得同步修改dateFormat。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:37:34