【问题标题】:Find current time is in between the time interval "Mon-Fri 11:00 am - 9:00 pm"查找当前时间在“周一至周五 11:00 am - 9:00 pm”的时间间隔之间
【发布时间】:2021-05-03 07:17:23
【问题描述】:

尝试使用 SimpleDateFormat 并没有得到如下预期的结果:

Mon, 11:00 am - 9:00 pm
Tue, 11:00 am - 9:00 pm
Wed, 11:00 am - 9:00 pm
Thu, 11:00 am - 9:00 pm
Fri, 11:00 am - 9:00 pm

如果当前时间介于这些时间之间,则需要返回 true。

【问题讨论】:

标签: java android datetime kotlin time


【解决方案1】:

假设您从某个地方以字符串的形式读取您的每日营业时间(在良好的设计中这不是必需的,但假设您的情况是这样),您首先需要一个数据结构来存储它们。我建议Map。我建议每天上课时间如下。

public class DailyHours {

    private static final DateTimeFormatter timeParser = new DateTimeFormatterBuilder()
            .parseCaseInsensitive()
            .appendPattern("h:mm a")
            .toFormatter(Locale.ENGLISH);
    
    private LocalTime opens;
    private LocalTime closes;
    
    public DailyHours(String times) {
        String[] hours = times.split(" - ");
        if (hours.length != 2) {
            throw new IllegalArgumentException("Improper format " + times + ", must be like 11:00 am - 9:00 pm");
        }
        opens = LocalTime.parse(hours[0], timeParser);
        closes = LocalTime.parse(hours[1], timeParser);
    }
    
    public boolean isBetween(LocalTime time) {
        return ! time.isBefore(opens) && time.isBefore(closes);
    }
}

现在我们可以通过这种方式将您的字符串读入您的地图:

    String[] openingHoursTable = {
            "Mon, 11:00 am - 9:00 pm",
            "Tue, 11:00 am - 9:00 pm",
            "Wed, 11:00 am - 9:00 pm",
            "Thu, 11:00 am - 9:00 pm",
            "Fri, 11:00 am - 9:00 pm"
    };
    
    Map<DayOfWeek, DailyHours> hoursPerDay = Arrays.stream(openingHoursTable)
            .map(s -> s.split(", "))
            .collect(Collectors.toMap(arr -> DayOfWeek.from(dayParser.parse(arr[0])), 
                    arr -> new DailyHours(arr[1])));

为此,我们需要以下格式化程序:

private static final DateTimeFormatter dayParser = DateTimeFormatter.ofPattern("EEE", Locale.ENGLISH);

完成此操作后,我们可以随时检查我们是否在营业时间内:

    ZonedDateTime currentTime = ZonedDateTime.now(ZoneId.systemDefault());
    DailyHours todaysHours = hoursPerDay.get(currentTime.getDayOfWeek());
    if (todaysHours == null) {
        System.out.println("Closed today");
    } else {
        System.out.println("Open now? " + todaysHours.isBetween(currentTime.toLocalTime()));
    }

刚刚跑步(我所在时区的星期五下午 5:40)我得到了:

现在开门了吗?真的

链接: Oracle tutorial: Date Time 解释如何使用 java.time。

【讨论】:

    【解决方案2】:

    java.time

    我建议你使用java.time 来完成它,它为你提供了一组丰富的 API。

    import java.time.DayOfWeek;
    import java.time.LocalDateTime;
    import java.time.ZoneId;
    import java.time.temporal.TemporalAdjusters;
    
    public class Main {
        public static void main(String[] args) {
            // Change the time-zone as per your requirement e.g. ZoneId.of("Europe/London")
            LocalDateTime now = LocalDateTime.now(ZoneId.systemDefault());
    
            LocalDateTime end = now.with(TemporalAdjusters.previousOrSame(DayOfWeek.FRIDAY))
                                    .withHour(21);
            
            boolean valid = false;
            for (LocalDateTime start = now.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)); !start
                    .isAfter(end); start = start.plusDays(1)) {
                if (!now.isBefore(start.withHour(11)) && !now.isAfter(start.withHour(21))) {
                    valid = true;
                    break;
                }
            }
    
            if (!valid) {
                System.out.println("Invalid");
            } else {
                System.out.println("Valid");
            }
        }
    }
    

    输出:

    Valid
    

    Trail: Date Time 了解现代日期时间 API。

    java.util 的日期时间 API 及其格式化 API SimpleDateFormat 已过时且容易出错。建议完全停止使用,转用modern date-time API

    【讨论】:

    • 如果3-4行代码就能完成同样的事情,真的需要让代码更复杂吗
    • @mightyWOZ - 如果您使用现代日期时间 API 发布一个不太复杂的答案,那就太好了。如果您不了解现代日期时间 API,则应该学习它,而不是教别人使用损坏的 java.util 日期时间 API。
    • @mightyWOZ - 我的回答中的最后一点包含帮助您使用 Java 8 日期时间 API 的链接。
    • @mightyWOZ - 你检查过Java 8+ APIs available through desugaring吗?
    • 很可能会崩溃。不是这样,别担心。根据大多数经验,使用陈旧且设计不佳的日期和时间类更容易出错。
    【解决方案3】:

    您可以使用Calendar 获取日期和时间值,然后只需执行检查日期和时间是否在所需范围内。

    val cal = Calendar.getInstance()
    val day = cal.get(Calendar.DAY_OF_WEEK)   // sunday 1.. saturday 7
    val hour = cal.get(Calendar.HOUR_OF_DAY)  // Hour in 24 hours format
    
    return (day in Calendar.MONDAY..Calendar.FRIDAY && hour in 11..21)
    

    【讨论】:

    • 感谢您的回答。如何将“周一至周四上午 11:00 - 晚上 10:00”转换为两个单独的日期?那么很容易找到当前时间是否在这两个日期之间。
    • 你能解释一下为什么我的回答不能解决你的问题吗?
    • 我建议你不要使用Calendar。该课程设计不良且早已过时。而是使用来自java.time, the modern Java date and time API 的类。
    • 我认为google 不知道您的意见。
    • 你是在暗示谷歌——利用 Java——从未读过Why do we need a new date and time library?我建议他们读过。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-10-14
    • 2012-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多