package ch.pollet.jzic.compiler;
import ch.pollet.jzic.datetime.DateTime;
import ch.pollet.jzic.datetime.DateTimeException;
import ch.pollet.jzic.parser.Parser;
import java.util.ArrayList;
import java.util.TreeSet;
import ch.pollet.jzic.timezone.Period;
import ch.pollet.jzic.timezone.Rule;
import ch.pollet.jzic.timezone.Database;
import ch.pollet.jzic.timezone.Zone;
/**
*
* @author Christophe Pollet
*/
public class Compiler {
Database db;
int minYear;
int maxYear;
public Compiler(Database db) {
this.db = db;
this.minYear = Integer.MIN_VALUE;
this.maxYear = 2050;
}
public void setMinYear(int beginYear) {
this.minYear = beginYear;
}
public void setMaxYear(int endYear) {
this.maxYear = endYear;
}
public void compile() throws DateTimeException {
db.resolveLinks();
for (String zoneName : db.getZones().keySet()) {
TreeSet<Period> compiledZone = computePeriods(db.getZones().get(zoneName));
compiledZone = removeBloatPeriods(compiledZone);
computeUtcTimes(compiledZone);
computeToDates(compiledZone);
db.addCompiledZone(zoneName, compiledZone);
}
}
private TreeSet<Period> computePeriods(TreeSet<Zone> zoneData) throws DateTimeException {
TreeSet<Period> compiledZone = new TreeSet<Period>();
DateTime from = new DateTime();
from.setYear(Integer.MIN_VALUE);
//from.setYear(minYear);
from.setMonth(1);
from.setDay(1);
from.setHour(0);
from.setMinute(0);
from.setSecond(0);
from.setType(DateTime.Type.UTC);
for (Zone zone : zoneData) {
Period period = new Period(zone);
period.setFrom(from);
if (period.getTo().getYear() > maxYear) {
period.getTo().setYear(maxYear);
}
compiledZone.add(period);
// find rules...
if (zone.getRule() != null) {
ArrayList<Rule> rules;
if ((rules = db.getRules().get(zone.getRule())) != null) {
for (Rule rule : rules) {
compiledZone.addAll(rule.toPeriods(period));
}
} else {
int offset = Parser.parseOffset(zone.getRule());
period.setOffset(period.getOffset() + offset);
period.isStdOffset(false);
}
}
from = period.getTo();
period.setTo(null);
}
return compiledZone;
}
private TreeSet<Period> removeBloatPeriods(TreeSet<Period> compiledZone) {
TreeSet<Period> newCompiledZone = new TreeSet<Period>();
Period previousPeriod = null;
for (Period period : compiledZone) {
if (previousPeriod == null) {
newCompiledZone.add(period);
} else {
if (!period.sameAs(previousPeriod)) {
newCompiledZone.add(period);
}
}
previousPeriod = period;
}
return newCompiledZone;
}
private void computeToDates(TreeSet<Period> compiledZone) {
Period previousPeriod = null;
for (Period period : compiledZone) {
if (previousPeriod != null) {
previousPeriod.setTo(period.getFrom());
}
previousPeriod = period;
}
DateTime to = new DateTime();
to.setYear(Integer.MAX_VALUE);
to.setMonth(12);
to.setDay(31);
to.setHour(23);
to.setMinute(59);
to.setSecond(59);
to.setType(DateTime.Type.UTC);
compiledZone.last().setTo(to);
}
private void computeUtcTimes(TreeSet<Period> compiledZone) throws DateTimeException {
int stdOffset = 0;
int dstOffset = 0;
for (Period period : compiledZone) {
period.getFrom().toUtc(stdOffset, dstOffset);
if (period.isStdOffset()) {
stdOffset = period.getOffset();
}
dstOffset = period.getOffset();
dstOffset = period.getOffset();
}
}
}