如何用正则匹配多格式营业时间并转换为目标数据库表?
解析多种格式营业时间并转换为数据库记录
我来帮你一步步搞定这个营业时间解析和转换的问题,咱们从匹配、解析到生成数据库记录全流程梳理:
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
相关产品推荐
相关产品推荐

