/* ********************************************************************** ** ** Copyright notice ** ** ** ** (c) 2005-2009 RSSOwl Development Team ** ** http://www.rssowl.org/ ** ** ** ** All rights reserved ** ** ** ** This program and the accompanying materials are made available under ** ** the terms of the Eclipse Public License v1.0 which accompanies this ** ** distribution, and is available at: ** ** http://www.rssowl.org/legal/epl-v10.html ** ** ** ** A copy is found in the file epl-v10.html and important notices to the ** ** license from the team is found in the textfile LICENSE.txt distributed ** ** in this package. ** ** ** ** This copyright notice MUST APPEAR in all copies of the file! ** ** ** ** Contributors: ** ** RSSOwl Development Team - initial API and implementation ** ** ** ** ********************************************************************** */ package org.rssowl.core.util; import org.eclipse.core.runtime.Assert; import org.rssowl.core.internal.persist.News; import org.rssowl.core.persist.INews; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.TimeZone; /** * Utility Class for working with <code>Dates</code>. * * @author bpasero */ public class DateUtils { /** 1 Day in Millis */ public static final long DAY = 24L * 60L * 60L * 1000L; /** 1 Week in Millis */ public static final long WEEK = 7 * DAY; /* An array of custom date formats */ private static final DateFormat[] CUSTOM_DATE_FORMATS; /* The Default Timezone to be used */ private static final TimeZone TIMEZONE = TimeZone.getTimeZone("UTC"); //$NON-NLS-1$ /** * @return A Calendar instance with the time being Today with a Time of * 0:00:00 */ public static Calendar getToday() { Calendar today = Calendar.getInstance(); today.set(Calendar.HOUR_OF_DAY, 0); today.set(Calendar.MINUTE, 0); today.set(Calendar.SECOND, 0); today.set(Calendar.MILLISECOND, 0); return today; } /** * @param date any {@link Date} to see if it is from today or later or not. * @param todayMidnightInMillies the time of the day at midnight. * @return <code>true</code> if the given {@link Date} is from today or later * as provided by the today parameter and <code>false</code> otherwise. */ public static boolean isAfterIncludingToday(Date date, long todayMidnightInMillies) { long time = date.getTime(); return todayMidnightInMillies <= time; } /** * Returns the first Date-Field from the given News that is not NULL. Tries * Modified-Date, Publish-Date, and Received-Date. The latter one is never * NULL so this Method will never return NULL at all. * * @param news The News to get the Date from. * @return Either Modified-Date, Publish-Date or Received-Date if the formers * are NULL. */ public static Date getRecentDate(INews news) { return ((News)news).fastGetRecentDate(); } /** * Works like getRecentData(INews news) with the difference of returning the * most recent date from a List of News. * * @param news A List of News to get the most recent Date from. * @return Either Modified-Date, Publish-Date or Received-Date from the most * recent News. */ public static Date getRecentDate(List<INews> news) { Assert.isTrue(!news.isEmpty()); Date mostRecentDate = null; for (INews newsitem : news) { Date date = getRecentDate(newsitem); if (mostRecentDate == null || date.after(mostRecentDate)) mostRecentDate = date; } return mostRecentDate; } /** * Tries different date formats to parse against the given string * representation to retrieve a valid Date object. * * @param strdate Date as String * @return Date The parsed Date */ public static Date parseDate(String strdate) { /* Return in case the string date is not set */ if (strdate == null || strdate.length() == 0) return null; Date result = null; strdate = strdate.trim(); if (strdate.length() > 10) { /* Open: deal with +4:00 (no zero before hour) */ if ((strdate.substring(strdate.length() - 5).indexOf("+") == 0 || strdate.substring(strdate.length() - 5).indexOf("-") == 0) && strdate.substring(strdate.length() - 5).indexOf(":") == 2) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ String sign = strdate.substring(strdate.length() - 5, strdate.length() - 4); strdate = strdate.substring(0, strdate.length() - 5) + sign + "0" + strdate.substring(strdate.length() - 4); //$NON-NLS-1$ } String dateEnd = strdate.substring(strdate.length() - 6); /* * try to deal with -05:00 or +02:00 at end of date replace with -0500 or * +0200 */ if ((dateEnd.indexOf("-") == 0 || dateEnd.indexOf("+") == 0) && dateEnd.indexOf(":") == 3) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ if (!"GMT".equals(strdate.substring(strdate.length() - 9, strdate.length() - 6))) { //$NON-NLS-1$ String oldDate = strdate; String newEnd = dateEnd.substring(0, 3) + dateEnd.substring(4); strdate = oldDate.substring(0, oldDate.length() - 6) + newEnd; } } } /* Try to parse the date */ int i = 0; while (i < CUSTOM_DATE_FORMATS.length) { try { /* * This Block needs to be synchronized, because the parse-Method in * SimpleDateFormat is not Thread-Safe. */ synchronized (CUSTOM_DATE_FORMATS[i]) { return CUSTOM_DATE_FORMATS[i].parse(strdate); } } catch (ParseException e) { i++; } catch (NumberFormatException e) { i++; } } return result; } /** Initialize the array of common date formats and formatter */ static { /* Create Date Formats */ final String[] possibleDateFormats = { /* RFC 1123 with 2-digit Year */ "EEE, dd MMM yy HH:mm:ss z", //$NON-NLS-1$ /* RFC 1123 with 4-digit Year */ "EEE, dd MMM yyyy HH:mm:ss z", //$NON-NLS-1$ /* RFC 1123 with no Timezone */ "EEE, dd MMM yy HH:mm:ss", //$NON-NLS-1$ /* Variant of RFC 1123 */ "EEE, MMM dd yy HH:mm:ss", //$NON-NLS-1$ /* RFC 1123 with no Seconds */ "EEE, dd MMM yy HH:mm z", //$NON-NLS-1$ /* Variant of RFC 1123 */ "EEE dd MMM yyyy HH:mm:ss", //$NON-NLS-1$ /* RFC 1123 with no Day */ "dd MMM yy HH:mm:ss z", //$NON-NLS-1$ /* RFC 1123 with no Day or Seconds */ "dd MMM yy HH:mm z", //$NON-NLS-1$ /* ISO 8601 slightly modified */ "yyyy-MM-dd'T'HH:mm:ssZ", //$NON-NLS-1$ /* ISO 8601 slightly modified */ "yyyy-MM-dd'T'HH:mm:ss'Z'", //$NON-NLS-1$ /* ISO 8601 slightly modified */ "yyyy-MM-dd'T'HH:mm:sszzzz", //$NON-NLS-1$ /* ISO 8601 slightly modified */ "yyyy-MM-dd'T'HH:mm:ss z", //$NON-NLS-1$ /* ISO 8601 */ "yyyy-MM-dd'T'HH:mm:ssz", //$NON-NLS-1$ /* ISO 8601 slightly modified */ "yyyy-MM-dd'T'HH:mm:ss.SSSz", //$NON-NLS-1$ /* ISO 8601 slightly modified */ "yyyy-MM-dd'T'HHmmss.SSSz", //$NON-NLS-1$ /* ISO 8601 slightly modified */ "yyyy-MM-dd'T'HH:mm:ss", //$NON-NLS-1$ /* ISO 8601 w/o seconds */ "yyyy-MM-dd'T'HH:mmZ", //$NON-NLS-1$ /* ISO 8601 w/o seconds */ "yyyy-MM-dd'T'HH:mm'Z'", //$NON-NLS-1$ /* RFC 1123 without Day Name */ "dd MMM yyyy HH:mm:ss z", //$NON-NLS-1$ /* RFC 1123 without Day Name and Seconds */ "dd MMM yyyy HH:mm z", //$NON-NLS-1$ /* Simple Date Format */ "yyyy-MM-dd", //$NON-NLS-1$ /* Simple Date Format */ "MMM dd, yyyy" //$NON-NLS-1$ }; /* Create the dateformats */ CUSTOM_DATE_FORMATS = new SimpleDateFormat[possibleDateFormats.length]; for (int i = 0; i < possibleDateFormats.length; i++) { CUSTOM_DATE_FORMATS[i] = new SimpleDateFormat(possibleDateFormats[i], Locale.ENGLISH); CUSTOM_DATE_FORMATS[i].setTimeZone(TIMEZONE); } } }