package com.goafanti.crawler.callback;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.alibaba.fastjson.JSON;
public class VacationFutureCallback extends CrawlerFutureCallback {
private String year = null;
private Pattern dateTime = null;
private Pattern dateTimePeriod = null;
private Pattern dateTimePeriod2 = null;
private Set vacations = null;
private Set workDays = null;
public VacationFutureCallback(Map result) {
setResult(result);
}
@Override
protected void handleWebpage(String pageContent) {
Pattern pattern = Pattern.compile("| ([\\s\\S]*?) | ", Pattern.MULTILINE);
Matcher m = pattern.matcher(pageContent);
if (m.find()) {
handleNotice(m.group(1));
}
}
private void handleNotice(String notice) {
Matcher yearMatcher = Pattern.compile("关于(\\d+)年").matcher(notice);
if (yearMatcher.find()) {
year = yearMatcher.group(1);
} else {
return;
}
List parts = new ArrayList<>();
Matcher linesMatcher = Pattern.compile("([\\s\\S]+?)
", Pattern.MULTILINE).matcher(notice);
while (linesMatcher.find()) {
parts.add(linesMatcher.group(1));
}
handleParts(parts);
}
private void handleParts(List parts) {
dateTime = Pattern.compile("(\\d+)月(\\d+)日");
dateTimePeriod = Pattern.compile("(\\d+)月(\\d+)日至(\\d+)日");
dateTimePeriod2 = Pattern.compile("(\\d+)月(\\d+)日至(\\d+)月(\\d+)日");
vacations = new HashSet<>();
workDays = new HashSet<>();
for (String part : parts) {
for (String s : part.split("<.*?>")) {
if (s.matches("\\d+月\\d+日.*")) {
handleLine(s);
}
}
}
Calendar c = Calendar.getInstance();
int y = Integer.parseInt(year);
c.set(y, 0, 1);
while (c.get(Calendar.YEAR) == y) {
int dow = c.get(Calendar.DAY_OF_WEEK);
if (dow == 7 || dow == 1) {
String ckey = getDateStr(c);
if (!workDays.contains(ckey)) {
vacations.add(ckey);
}
}
c.add(Calendar.DATE, 1);
}
if (this.getResult() != null) {
this.getResult().put(year, JSON.toJSONString(vacations));
}
}
private void handleLine(String line) {
for (String s : line.split("。")) {
boolean isVacation = s.indexOf("上班") == -1;
if (findNoPeriod2(s, isVacation) && findNoPeriod(s, isVacation)) {
Matcher dtm = dateTime.matcher(s);
while (dtm.find()) {
if (isVacation) {
vacations.add(getDateStr(Integer.parseInt(dtm.group(1)), Integer.parseInt(dtm.group(2))));
} else {
workDays.add(getDateStr(Integer.parseInt(dtm.group(1)), Integer.parseInt(dtm.group(2))));
}
}
}
}
}
private boolean findNoPeriod2(String s, boolean isVacation) {
Matcher dtp2m = dateTimePeriod2.matcher(s);
if (dtp2m.find()) {
addPeriodToSet(dtp2m.group(1), dtp2m.group(2), dtp2m.group(3), dtp2m.group(4),
isVacation ? vacations : workDays);
return false;
}
return true;
}
private boolean findNoPeriod(String s, boolean isVacation) {
Matcher dtp2m = dateTimePeriod.matcher(s);
if (dtp2m.find()) {
addPeriodToSet(dtp2m.group(1), dtp2m.group(2), dtp2m.group(1), dtp2m.group(3),
isVacation ? vacations : workDays);
return false;
}
return true;
}
private void addPeriodToSet(String stM, String stD, String edM, String edD, Set set) {
Calendar st = Calendar.getInstance();
st.set(Integer.parseInt(year), Integer.parseInt(stM) - 1, Integer.parseInt(stD));
Calendar ed = (Calendar) st.clone();
ed.set(Integer.parseInt(year), Integer.parseInt(edM) - 1, Integer.parseInt(edD));
while (ed.after(st)) {
set.add(getDateStr(st));
st.add(Calendar.DATE, 1);
}
set.add(getDateStr(ed));
}
private String getDateStr(Calendar c) {
return getDateStr(c.get(Calendar.MONTH) + 1, c.get(Calendar.DATE));
}
private String getDateStr(int m, int d) {
StringBuilder sb = new StringBuilder(year);
if (m < 10) {
sb.append(0);
}
sb.append(m);
if (d < 10) {
sb.append(0);
}
sb.append(d);
return sb.toString();
}
}