我有以下字符串表示我需要解析的日期范围:
import { combineReducers } from 'redux'
import {ADD_TODO,
FORK_TODO,
ADDED_BUTTON,
TOGGLE_BUTTON,
EDIT_TODO,
DELETE_TODO,
FILTER_TODO_UP,
FILTER_TODO_DOWN,
CHANGE_STATUS,
VISIBLE_TODO_ALL,
VISIBLE_TODO_ACTIVE,
VISIBLE_TODO_DONED } from '../Variables/Variables'
const initialState = {
iteams: {
todos:[],
buttons:[]
}
}
function TodoApp(state, action) {
if (typeof state === 'undefined') {
return initialState;
}
switch (action.type) {
case ADD_TODO:
console.log(state.iteams);
return Object.assign({}, state, {
iteams: {
todos: [
...state.iteams.todos,
{
id: action.id,
text: action.text + '___' + action.id,
status: action.status
}
],
buttons: [
...state.iteams.buttons,
{
id: action.id,
done: false,
status: action.status
}
]
}
});
case CHANGE_STATUS:
console.log(state.iteams, action.status);
return {
iteams: {
todos: [
...state.iteams.todos.map(todo => {
return (todo.id === parseInt(action.id)
&& todo.status !== action.status)
? {...state.iteams.todo,
id: todo.id,
text: todo.text,
status: action.status
} : todo
})
],
buttons: [
...state.iteams.buttons.map(button => {
return (button.id === parseInt(action.id)
&& button.status !== action.status) ?
{...state.iteams.button,
id: button.id,
done: button.done,
status: action.status
} : button
})
]
}
};
case VISIBLE_TODO_ALL:
console.log('VISIBLE_TODO_ALL', state.iteams);
return Object.assign({}, {
...state
});
case VISIBLE_TODO_ACTIVE:
console.log('VISIBLE_TODO_ACTIVE', state.iteams);
return Object.assign({}, {
iteams: {
todos: state.iteams.todos.filter(iteam =>
iteam.status === 'active'
),
buttons: state.iteams.buttons.filter(button =>
button.status === 'active'
)
}
});
case VISIBLE_TODO_DONED:
console.log('VISIBLE_TODO_DONED', state.iteams);
return Object.assign({}, {
iteams: {
todos: state.iteams.todos.filter(iteam =>
iteam.status === 'done'
),
buttons: state.iteams.buttons.filter(button =>
button.status === 'done'
)
}
});
default:
return state;
}
}
export default TodoApp
它由2个ISO日期字符串组成,以2018-10-20:2019-10-20
通过将重复的日期范围与其他文本混合,字符串会变得更复杂。这可以通过正则表达式完成。
然而,鉴于最新的Java具有日期/时间支持,大多数编码人员在这里和其他地方都欣喜若狂,是否可以使用:
的解析器或自定义LocalDate
为了识别我的String中哪些位是ISO-date的候选者并捕获它们?
更好的是,如何从DateTimeFormatter
(标识ISO日期的正则表达式,假设有一个)中提取验证正则表达式,并将其与我自己的正则表达式合并/编译为字符串的其余部分
我觉得在我的代码中编写另一个ISO-date正则表达式时感觉很舒服,因为Java中已经存在一个正则表达式而且我只是重复使用它。
请注意,我不是要求正则表达式。我能做到。
另请注意,我的示例字符串可以包含其他日期/时间格式,例如时区和毫秒以及所有的哨声。
答案 0 :(得分:0)
Regex + Date Parser是正确的选择。
您必须自己编写正则表达式,因为日期解析器不使用正则表达式。
您的选择是否正则表达式可以简单,例如月份\d{2}
,让日期解析器验证号码范围,或者是否必须更严格,例如(?:0[1-9]|1[0-2])
(01
- 12
)。在正则表达式中不应该进行范围检查,例如28 vs 30 vs 31天。让日期解析器处理它,并且因为一些值范围由日期解析器处理,所以也可以让它全部处理它们,即一个简单的正则表达式完全没问题。
答案 1 :(得分:0)
实际上,DateTimeFormatter
没有内部正则表达式。它uses a CompositePrinterParser
,后者又使用array of DateTimePrinterParser
instances(inner interface of DateTimeFormatterBuilder
),其中每个实例负责解析/格式化特定字段。
IMO,正则表达式不是这里最好的方法。如果您知道所有日期都以:
分隔,为什么不简单地拆分字符串并尝试单独解析这些部分?这样的事情:
String dates = // big string with dates separated by :
DateTimeFormatter parser = // create a formatter for your patterns
for (String s : dates.split(":")) {
parser.parse(s); // if "s" is invalid, it throws exception
}
如果您只想验证字符串,如上所述调用parse
就足够了 - 如果字符串无效,它将抛出异常。
要支持多种格式,您可以使用DateTimeFormatterBuilder::appendOptional
。例如:
DateTimeFormatter parser = new DateTimeFormatterBuilder()
// full ISO8601 with date/time and UTC offset (ex: 2011-12-03T10:15:30+01:00)
.appendOptional(DateTimeFormatter.ISO_OFFSET_DATE_TIME)
// date/time without UTC offset (ex: 2011-12-03T10:15:30)
.appendOptional(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
// just date (ex: 2011-12-03)
.appendOptional(DateTimeFormatter.ISO_LOCAL_DATE)
// some custom format (day/month/year)
.appendOptional(DateTimeFormatter.ofPattern("dd/MM/yyyy"))
// ... add as many you need
// create formatter
.toFormatter();
支持多种格式的正则表达式(正如你所说,“其他日期/时间格式,例如时区和毫秒以及所有哨声”)是可能的,但正则表达式不适合验证日期 - 例如第零天,日> 30对于非闰年2月29日的所有月份无效,分钟> 60等。
DateTimeFormatter
将验证所有这些棘手的细节,而正则表达式只能保证您的数字和分隔符位于正确的位置,并且不会验证这些值。因此,无论正则表达式如何,你都必须解析日期(在这种情况下,恕我直言,正则表达式使用正则表达式无用)。