/* * Copyright (C) 2010-2011 Geometer Plus <contact@geometerplus.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ package org.geometerplus.fbreader.network.atom; public abstract class ATOMDateConstruct extends ATOMCommonAttributes implements Comparable<ATOMDateConstruct> { public int Year; public int Month; public int Day; public int Hour; public int Minutes; public int Seconds; public float SecondFraction; public int TZHour; public int TZMinutes; public ATOMDateConstruct() { } public ATOMDateConstruct(int year) { Year = year; } public ATOMDateConstruct(int year, int month, int day) { Year = year; Month = month; Day = day; } public ATOMDateConstruct(int year, int month, int day, int hour, int minutes, int seconds) { Year = year; Month = month; Day = day; Hour = hour; Minutes = minutes; Seconds = seconds; } public ATOMDateConstruct(int year, int month, int day, int hour, int minutes, int seconds, float sfract) { Year = year; Month = month; Day = day; Hour = hour; Minutes = minutes; Seconds = seconds; SecondFraction = sfract; } public ATOMDateConstruct(int year, int month, int day, int hour, int minutes, int seconds, float sfract, int tzhour, int tzminutes) { Year = year; Month = month; Day = day; Hour = hour; Minutes = minutes; Seconds = seconds; TZHour = tzhour; TZMinutes = tzminutes; SecondFraction = sfract; } public static boolean parse(String str, ATOMDateConstruct dateTime) { dateTime.Year = 0; dateTime.Month = 0; dateTime.Day = 0; dateTime.Hour = 0; dateTime.Minutes = 0; dateTime.Seconds = 0; dateTime.SecondFraction = 0.0f; dateTime.TZHour = 0; dateTime.TZMinutes = 0; if (str == null || dateTime == null) { return false; } final int len = str.length(); if (len != 4 && len != 7 && len != 10 && len != 17 && len != 20 && len < 22) { return false; } int num = 0, sign = 1; float fnum = 0.0f, fmult = 0.1f; int start, end, log; char ch; end = 4; start = 0; log = 0; while (start < len) { ch = str.charAt(start++); if (!Character.isDigit(ch)) { return false; } num = 10 * num + ((int) (ch - '0')); fnum += fmult * ((int) (ch - '0')); fmult *= 0.1f; if (start == end) { switch (log) { case 0: dateTime.Year = num; break; case 1: dateTime.Month = num; break; case 2: dateTime.Day = num; break; case 3: dateTime.Hour = num; break; case 4: dateTime.Minutes = num; break; case 5: dateTime.Seconds = num; break; case 6: dateTime.SecondFraction = fnum; break; case 7: dateTime.TZHour = sign * num; break; case 8: dateTime.TZMinutes = sign * num; break; default: return false; } num = 0; fnum = 0.0f; fmult = 0.1f; if (start == len) return true; switch (log) { case 0: case 1: if (str.charAt(start++) != '-') return false; end = start + 2; break; case 2: if (str.charAt(start++) != 'T') return false; end = start + 2; break; case 3: case 7: if (str.charAt(start++) != ':') return false; end = start + 2; break; case 4: ch = str.charAt(start++); if (ch == ':') { end = start + 2; } else if (ch == '+' || ch == '-') { sign = (ch == '-') ? -1 : 1; log += 2; end = start + 2; } else if (ch == 'Z') { return true; } else return false; break; case 5: ch = str.charAt(start++); if (ch == '.') { end = start; while (Character.isDigit(str.charAt(++end))) /* NOP */; } else if (ch == '+' || ch == '-') { sign = (ch == '-') ? -1 : 1; log += 1; end = start + 2; } else if (ch == 'Z') { return true; } else return false; break; case 6: ch = str.charAt(start++); if (ch == '+' || ch == '-') { sign = (ch == '-') ? -1 : 1; end = start + 2; } else if (ch == 'Z') { return true; } else return false; break; //case 8: default: return false; } ++log; } } return false; } private static void appendChars(StringBuilder buffer, char ch, int count) { while (count-- > 0) { buffer.append(ch); } } public final String getDateTime(boolean brief) { StringBuilder timezone = new StringBuilder("Z"); if (TZMinutes != 0 || TZHour != 0) { int tzminnum = TZMinutes; int tzhournum = TZHour; char sign; if (tzhournum == 0) { sign = (tzminnum >= 0) ? '+' : '-'; } else { sign = (tzhournum > 0) ? '+' : '-'; if (tzhournum > 0 && tzminnum < 0) { --tzhournum; tzminnum = 60 + tzminnum; } else if (tzhournum < 0 && tzminnum > 0) { ++tzhournum; tzminnum = 60 - tzminnum; } } String tzmin = String.valueOf(tzminnum < 0 ? -tzminnum : tzminnum); String tzhour = String.valueOf(tzhournum < 0 ? -tzhournum : tzhournum); timezone.append(sign); appendChars(timezone, '0', 2 - tzhour.length()); timezone.append(tzhour); timezone.append(':'); appendChars(timezone, '0', 2 - tzmin.length()); timezone.append(tzmin); } StringBuilder time = new StringBuilder(); StringBuilder temp = new StringBuilder(); if (SecondFraction >= 0.01f) { int sfrnum = Math.round(100 * SecondFraction); String sfr = String.valueOf(sfrnum); time.append('.'); appendChars(time, '0', 2 - sfr.length()); time.append(sfr); } if (!brief || time.length() != 0 || Seconds != 0) { String sec = String.valueOf(Seconds); temp.append(':'); appendChars(temp, '0', 2 - sec.length()); temp.append(sec); time.insert(0, temp.toString()); temp.delete(0, temp.length()); } if (!brief || time.length() != 0 || Hour != 0 || Minutes != 0 || timezone.length() > 1) { String hour = String.valueOf(Hour); String min = String.valueOf(Minutes); appendChars(temp, '0', 2 - hour.length()); temp.append(hour); temp.append(':'); appendChars(temp, '0', 2 - min.length()); temp.append(min); time.insert(0, temp.toString()); temp.delete(0, temp.length()); } StringBuilder date = new StringBuilder(); if (!brief || time.length() != 0 || Day != 0) { String day = String.valueOf(Day); date.append('-'); appendChars(date, '0', 2 - day.length()); date.append(day); } if (!brief || date.length() != 0 || Month != 0) { String month = String.valueOf(Month); temp.append('-'); appendChars(temp, '0', 2 - month.length()); temp.append(month); date.insert(0, temp.toString()); temp.delete(0, temp.length()); } String year = String.valueOf(Year); appendChars(temp, '0', 4 - year.length()); temp.append(year); date.insert(0, temp.toString()); temp.delete(0, temp.length()); if (!brief || time.length() != 0) { date.append('T'); date.append(time.toString()); date.append(timezone.toString()); } return date.toString(); } @Override public String toString() { return getDateTime(false); } private static final int[] DAYS_IN_MONTHS = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; private int daysInMonth(int month, int year) { --month; while (month > 11) month -= 12; while (month < 0) month += 12; if (month == 1 && ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)) { return DAYS_IN_MONTHS[1] + 1; } return DAYS_IN_MONTHS[month]; } public int compareTo(ATOMDateConstruct date) { int dateYear = date.Year; int dateMonth = date.Month; int dateDay = date.Day; int dateHour = date.Hour; int dateMinutes = date.Minutes; if (TZHour != date.TZHour || TZMinutes != date.TZMinutes) { dateMinutes += TZMinutes - date.TZMinutes; while (dateMinutes < 0) { dateMinutes += 60; --dateHour; } while (dateMinutes > 59) { dateMinutes -= 60; ++dateHour; } dateHour += TZHour - date.TZHour; while (dateHour < 0) { dateHour += 24; --dateDay; } while (dateHour > 23) { dateHour -= 24; ++dateDay; } while (dateDay < 1) dateDay += daysInMonth(--dateMonth, dateYear); while (dateDay > daysInMonth(dateMonth, dateYear)) dateDay -= daysInMonth(dateMonth++, dateYear); while (dateMonth < 1) { dateMonth += 12; --dateYear; } while (dateMonth > 12) { dateMonth -= 12; ++dateYear; } } if (Year != dateYear) return Year - dateYear; if (Month != dateMonth) return Month - dateMonth; if (Day != dateDay) return Day - dateDay; if (Hour != dateHour) return Hour - dateHour; if (Minutes != dateMinutes) return Minutes - dateMinutes; if (Seconds != date.Seconds) return Seconds - date.Seconds; return Math.round(100 * SecondFraction) - Math.round(100 * date.SecondFraction); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof ATOMDateConstruct)) { return false; } return compareTo((ATOMDateConstruct) obj) == 0; } };