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

如何用正则匹配多格式营业时间并转换为目标数据库表?

解析多种格式营业时间并转换为数据库记录

我来帮你一步步搞定这个营业时间解析和转换的问题,咱们从匹配、解析到生成数据库记录全流程梳理:

1. 用正则拆分营业时间块

首先得把杂乱的营业时间字符串拆成一个个独立的时间段单元(比如Mo-Fr 10:00-18:00或者Mi 09:30-19:00),可以用这个正则表达式来匹配每个单元:

([A-Za-z, -]+)\s+(\d{1,2}:\d{2})-(\d{1,2}:\d{2})
  • 第一个捕获组([A-Za-z, -]+):负责抓取日期部分(包含缩写、逗号、空格、连字符)
  • 第二个捕获组(\d{1,2}:\d{2}):抓取开门时间
  • 第三个捕获组(\d{1,2}:\d{2}):抓取关门时间

2. 解析日期部分到数字

先定义日期缩写和DAY_OF_WEEK数字的映射关系(1=周一Mo,7=周日So):

private static final Map<String, Integer> DAY_MAP = new HashMap<>() {{
    put("Mo", 1);
    put("Di", 2);
    put("Mi", 3);
    put("Do", 4);
    put("Fr", 5);
    put("Sa", 6);
    put("So", 7);
}};

然后处理三种日期格式:

  • 单个日期:比如Sa → 直接映射为6
  • 多日期逗号分隔:比如Mo, Di, Do, Fr → 拆分每个缩写,分别映射
  • 日期范围:比如Mo-Fr或Mo - Fr → 拆分起始/结束日期,生成中间所有日期的数字(比如Mo到Fr就是1、2、3、4、5)

3. 时间转换为秒数

把HH:MM格式转成当天的秒数,方便存入数据库:

private static int timeToSeconds(String time) {
    String[] parts = time.split(":");
    int hours = Integer.parseInt(parts[0]);
    int minutes = Integer.parseInt(parts[1]);
    return hours * 3600 + minutes * 60;
}

比如10:00就是36000,09:30就是34200。

4. 完整实现代码(Java)

下面是一个可直接用的示例,输入营业时间字符串就能生成符合数据库结构的记录:

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class OpeningHoursParser {
    private static final Map<String, Integer> DAY_MAP = new HashMap<>() {{
        put("Mo", 1);
        put("Di", 2);
        put("Mi", 3);
        put("Do", 4);
        put("Fr", 5);
        put("Sa", 6);
        put("So", 7);
    }};
    private static final Pattern BLOCK_PATTERN = Pattern.compile("([A-Za-z, -]+)\\s+(\\d{1,2}:\\d{2})-(\\d{1,2}:\\d{2})");

    public static List<OpeningHourRecord> parse(String openingHoursStr, int entityId) {
        List<OpeningHourRecord> records = new ArrayList<>();
        Matcher matcher = BLOCK_PATTERN.matcher(openingHoursStr);
        
        while (matcher.find()) {
            String datePart = matcher.group(1).trim();
            String openTime = matcher.group(2);
            String closeTime = matcher.group(3);
            
            int openSeconds = timeToSeconds(openTime);
            int closeSeconds = timeToSeconds(closeTime);
            
            // 解析日期部分为数字列表
            List<Integer> dayNumbers = parseDatePart(datePart);
            
            // 生成每条数据库记录
            for (int day : dayNumbers) {
                records.add(new OpeningHourRecord(entityId, day, openSeconds, closeSeconds));
            }
        }
        return records;
    }

    private static List<Integer> parseDatePart(String datePart) {
        List<Integer> days = new ArrayList<>();
        String[] items = datePart.split(",");
        for (String item : items) {
            item = item.trim();
            if (item.contains("-")) {
                // 处理带空格/不带空格的日期范围
                String[] range = item.split("\\s*-\\s*");
                Integer start = DAY_MAP.get(range[0].trim());
                Integer end = DAY_MAP.get(range[1].trim());
                if (start != null && end != null) {
                    for (int i = start; i <= end; i++) {
                        days.add(i);
                    }
                }
            } else {
                // 处理单个日期
                Integer day = DAY_MAP.get(item);
                if (day != null) {
                    days.add(day);
                }
            }
        }
        return days;
    }

    private static int timeToSeconds(String time) {
        String[] parts = time.split(":");
        int hours = Integer.parseInt(parts[0]);
        int minutes = Integer.parseInt(parts[1]);
        return hours * 3600 + minutes * 60;
    }

    // 对应数据库表的实体类
    public static class OpeningHourRecord {
        private int entityId;
        private int dayOfWeek;
        private int open;
        private int close;
        private Date created;
        private Date updated;

        public OpeningHourRecord(int entityId, int dayOfWeek, int open, int close) {
            this.entityId = entityId;
            this.dayOfWeek = dayOfWeek;
            this.open = open;
            this.close = close;
            this.created = new Date();
            this.updated = new Date();
        }

        // 可按需添加getter/setter
    }

    public static void main(String[] args) {
        String testStr = "Mo, Di, Do, Fr 10:00-19:00, Mi 09:30-19:00, Sa 10:00-18:30";
        List<OpeningHourRecord> records = parse(testStr, 1);
        // 这里可以将records批量插入数据库
        for (OpeningHourRecord record : records) {
            System.out.printf("ENTITY: %d, DAY: %d, OPEN: %d, CLOSE: %d%n",
                    record.entityId, record.dayOfWeek, record.open, record.close);
        }
    }
}

5. 注意点

  • 确保所有日期缩写都在DAY_MAP里有映射,避免解析失败
  • 正则里的\\s*-\\s*兼容了带空格和不带空格的范围写法(比如Mo-Fr和Mo - Fr)
  • CREATED和UPDATED字段这里用了当前时间,你可以根据业务需求调整

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 21:42:36