All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.codehaus.groovy.runtime.DateGroovyMethods Maven / Gradle / Ivy

There is a newer version: 3.0.21
Show newest version
/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 */
package org.codehaus.groovy.runtime;

import groovy.lang.Closure;
import groovy.lang.GroovyRuntimeException;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.TimeZone;

/**
 * This class defines new groovy methods which appear on normal JDK
 * Date and Calendar classes inside the Groovy environment.
 */
public class DateGroovyMethods extends DefaultGroovyMethodsSupport {

    /**
     * Support the subscript operator for a Date.
     *
     * @param self  a Date
     * @param field a Calendar field, e.g. MONTH
     * @return the value for the given field, e.g. FEBRUARY
     * @see java.util.Calendar
     * @since 1.5.5
     */
    public static int getAt(Date self, int field) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(self);
        return cal.get(field);
    }

    /**
     * Convert a Date to a Calendar.
     *
     * @param self a Date
     * @return a Calendar corresponding to the given Date
     * @since 1.7.6
     */
    public static Calendar toCalendar(Date self) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(self);
        return cal;
    }

    /**
     * Support the subscript operator for a Calendar.
     *
     * @param self  a Calendar
     * @param field a Calendar field, e.g. MONTH
     * @return the value for the given field, e.g. FEBRUARY
     * @see java.util.Calendar
     * @since 1.7.3
     */
    public static int getAt(Calendar self, int field) {
        return self.get(field);
    }

    /**
     * Support the subscript operator for mutating a Calendar.
     * Example usage:
     * 
     * import static java.util.Calendar.*
     * def cal = Calendar.instance
     * cal[DAY_OF_WEEK] = MONDAY
     * cal[MONTH] = MARCH
     * println cal.time // A Monday in March
     * 
* * @param self A Calendar * @param field A Calendar field, e.g. MONTH * @param value The value for the given field, e.g. FEBRUARY * @see java.util.Calendar#set(int, int) * @since 1.7.3 */ public static void putAt(Calendar self, int field, int value) { self.set(field, value); } /** * Support the subscript operator for mutating a Date. * * @param self A Date * @param field A Calendar field, e.g. MONTH * @param value The value for the given field, e.g. FEBRUARY * @see #putAt(java.util.Calendar, int, int) * @see java.util.Calendar#set(int, int) * @since 1.7.3 */ public static void putAt(Date self, int field, int value) { Calendar cal = Calendar.getInstance(); cal.setTime(self); putAt(cal, field, value); self.setTime(cal.getTimeInMillis()); } /** * Support mutating a Calendar with a Map. *

* The map values are the normal values provided as the * second parameter to java.util.Calendar#set(int, int). * The keys can either be the normal fields values provided as * the first parameter to that method or one of the following Strings: *

* * * * * * * * *
Calendar index values
yearCalendar.YEAR
monthCalendar.MONTH
dateCalendar.DATE
dayOfMonthCalendar.DATE
hourOfDayCalendar.HOUR_OF_DAY
minuteCalendar.MINUTE
secondCalendar.SECOND
* Example usage: *
     * import static java.util.Calendar.*
     * def cal = Calendar.instance
     * def m = [:]
     * m[YEAR] = 2010
     * m[MONTH] = DECEMBER
     * m[DATE] = 25
     * cal.set(m)
     * println cal.time // Christmas 2010
     *
     * cal.set(year:2011, month:DECEMBER, date:25)
     * println cal.time // Christmas 2010
     * 
* * @param self A Calendar * @param updates A Map of Calendar keys and values * @see java.util.Calendar#set(int, int) * @see java.util.Calendar#set(int, int, int, int, int, int) * @since 1.7.3 */ public static void set(Calendar self, Map updates) { for (Map.Entry entry : updates.entrySet()) { Object key = entry.getKey(); if (key instanceof String) key = CAL_MAP.get(key); if (key instanceof Integer) self.set((Integer) key, entry.getValue()); } } /** * Legacy alias for copyWith. Will be deprecated and removed in future versions of Groovy. * * @see #copyWith(java.util.Calendar, java.util.Map) * @since 1.7.3 */ public static Calendar updated(Calendar self, Map updates) { Calendar result = (Calendar) self.clone(); set(result, updates); return result; } /** * Support creating a new Date having similar properties to * an existing Date (which remains unaltered) but with * some fields updated according to a Map of changes. *

* Example usage: *

     * import static java.util.Calendar.YEAR
     * def now = Calendar.instance
     * def nextYear = now[YEAR] + 1
     * def oneYearFromNow = now.copyWith(year: nextYear)
     * println now.time
     * println oneYearFromNow.time
     * 
* * @param self A Calendar * @param updates A Map of Calendar keys and values * @return The newly created Calendar * @see java.util.Calendar#set(int, int) * @see java.util.Calendar#set(int, int, int, int, int, int) * @see #set(java.util.Calendar, java.util.Map) * @since 2.2.0 */ public static Calendar copyWith(Calendar self, Map updates) { Calendar result = (Calendar) self.clone(); set(result, updates); return result; } /** * Support mutating a Date with a Map. *

* The map values are the normal values provided as the * second parameter to java.util.Calendar#set(int, int). * The keys can either be the normal fields values provided as * the first parameter to that method or one of the following Strings: *

* * * * * * * * *
Calendar index values
yearCalendar.YEAR
monthCalendar.MONTH
dateCalendar.DATE
dayOfMonthCalendar.DATE
hourOfDayCalendar.HOUR_OF_DAY
minuteCalendar.MINUTE
secondCalendar.SECOND
* Example usage: *
     * import static java.util.Calendar.YEAR
     * def date = new Date()
     * def nextYear = date[YEAR] + 1
     * date.set(year: nextYear)
     * println date
     * 
* * @param self A Date * @param updates A Map of Calendar keys and values * @see java.util.Calendar#set(int, int) * @see #set(java.util.Calendar, java.util.Map) * @since 1.7.3 */ public static void set(Date self, Map updates) { Calendar cal = Calendar.getInstance(); cal.setTime(self); set(cal, updates); self.setTime(cal.getTimeInMillis()); } /** * Legacy alias for copyWith. Will be deprecated and removed in future versions of Groovy. * * @see #copyWith(java.util.Date, java.util.Map) * @since 1.7.3 */ public static Date updated(Date self, Map updates) { Calendar cal = Calendar.getInstance(); cal.setTime(self); set(cal, updates); return cal.getTime(); } /** * Support creating a new Date having similar properties to * an existing Date (which remains unaltered) but with * some fields updated according to a Map of changes. *

* Example usage: *

     * import static java.util.Calendar.YEAR
     * def today = new Date()
     * def nextYear = today[YEAR] + 1
     * def oneYearFromNow = today.copyWith(year: nextYear)
     * println today
     * println oneYearFromNow
     * 
* * @param self A Date * @param updates A Map of Calendar keys and values * @return The newly created Date * @see java.util.Calendar#set(int, int) * @see #set(java.util.Date, java.util.Map) * @see #copyWith(java.util.Calendar, java.util.Map) * @since 2.2.0 */ public static Date copyWith(Date self, Map updates) { Calendar cal = Calendar.getInstance(); cal.setTime(self); set(cal, updates); return cal.getTime(); } private static final Map CAL_MAP = new HashMap(); static { CAL_MAP.put("year", Calendar.YEAR); CAL_MAP.put("month", Calendar.MONTH); CAL_MAP.put("date", Calendar.DATE); CAL_MAP.put("dayOfMonth", Calendar.DATE); CAL_MAP.put("hourOfDay", Calendar.HOUR_OF_DAY); CAL_MAP.put("minute", Calendar.MINUTE); CAL_MAP.put("second", Calendar.SECOND); } /** * Increment a Date by one day. * * @param self a Date * @return the next days date * @since 1.0 */ public static Date next(Date self) { return plus(self, 1); } /** * Increment a Calendar by one day. * * @param self a Calendar * @return a new Calendar set to the next day * @since 1.8.7 */ public static Calendar next(Calendar self) { Calendar result = (Calendar) self.clone(); result.add(Calendar.DAY_OF_YEAR, 1); return result; } /** * Decrement a Calendar by one day. * * @param self a Calendar * @return a new Calendar set to the previous day * @since 1.8.7 */ public static Calendar previous(Calendar self) { Calendar result = (Calendar) self.clone(); result.add(Calendar.DAY_OF_YEAR, -1); return result; } /** * Increment a java.sql.Date by one day. * * @param self a java.sql.Date * @return the next days date * @since 1.0 */ public static java.sql.Date next(java.sql.Date self) { return new java.sql.Date(next((Date) self).getTime()); } /** * Decrement a Date by one day. * * @param self a Date * @return the previous days date * @since 1.0 */ public static Date previous(Date self) { return minus(self, 1); } /** * Decrement a java.sql.Date by one day. * * @param self a java.sql.Date * @return the previous days date * @since 1.0 */ public static java.sql.Date previous(java.sql.Date self) { return new java.sql.Date(previous((Date) self).getTime()); } /** * Add a number of days to this date and returns the new date. * * @param self a Date * @param days the number of days to increase * @return the new date * @since 1.0 */ public static Date plus(Date self, int days) { Calendar calendar = (Calendar) Calendar.getInstance().clone(); calendar.setTime(self); calendar.add(Calendar.DAY_OF_YEAR, days); return calendar.getTime(); } /** * Add a number of days to this date and returns the new date. * * @param self a java.sql.Date * @param days the number of days to increase * @return the new date * @since 1.0 */ public static java.sql.Date plus(java.sql.Date self, int days) { return new java.sql.Date(plus((Date) self, days).getTime()); } /** * Add number of days to this Timestamp and returns the new Timestamp object. * * @param self a Timestamp * @param days the number of days to increase * @return the new Timestamp */ public static Timestamp plus(Timestamp self, int days) { Calendar calendar = (Calendar) Calendar.getInstance().clone(); calendar.setTime(self); calendar.add(Calendar.DAY_OF_YEAR, days); Timestamp ts = new Timestamp(calendar.getTime().getTime()); ts.setNanos(self.getNanos()); return ts; } /** * Subtract a number of days from this date and returns the new date. * * @param self a Date * @param days the number of days to subtract * @return the new date * @since 1.0 */ public static Date minus(Date self, int days) { return plus(self, -days); } /** * Subtract a number of days from this date and returns the new date. * * @param self a java.sql.Date * @param days the number of days to subtract * @return the new date * @since 1.0 */ public static java.sql.Date minus(java.sql.Date self, int days) { return new java.sql.Date(minus((Date) self, days).getTime()); } /** * Subtract a number of days from this Timestamp and returns the new Timestamp object. * * @param self a Timestamp * @param days the number of days to subtract * @return the new Timestamp */ public static Timestamp minus(Timestamp self, int days) { return plus(self, -days); } /** * Subtract another date from this one and return the number of days of the difference. *

* Date self = Date then + (Date self - Date then) *

* IOW, if self is before then the result is a negative value. * * @param self a Calendar * @param then another Calendar * @return number of days * @since 1.6.0 */ public static int minus(Calendar self, Calendar then) { Calendar a = self; Calendar b = then; boolean swap = a.before(b); if (swap) { Calendar t = a; a = b; b = t; } int days = 0; b = (Calendar) b.clone(); while (a.get(Calendar.YEAR) > b.get(Calendar.YEAR)) { days += 1 + (b.getActualMaximum(Calendar.DAY_OF_YEAR) - b.get(Calendar.DAY_OF_YEAR)); b.set(Calendar.DAY_OF_YEAR, 1); b.add(Calendar.YEAR, 1); } days += a.get(Calendar.DAY_OF_YEAR) - b.get(Calendar.DAY_OF_YEAR); if (swap) days = -days; return days; } /** * Subtract another Date from this one and return the number of days of the difference. *

* Date self = Date then + (Date self - Date then) *

* IOW, if self is before then the result is a negative value. * * @param self a Date * @param then another Date * @return number of days * @since 1.6.0 */ public static int minus(Date self, Date then) { Calendar a = (Calendar) Calendar.getInstance().clone(); a.setTime(self); Calendar b = (Calendar) Calendar.getInstance().clone(); b.setTime(then); return minus(a, b); } /** *

Create a String representation of this date according to the given * format pattern. *

*

For example, if the system timezone is GMT, * new Date(0).format('MM/dd/yy') would return the string * "01/01/70". See documentation for {@link java.text.SimpleDateFormat} * for format pattern use. *

*

Note that a new DateFormat instance is created for every * invocation of this method (for thread safety). * * @param self a Date * @param format the format pattern to use according to {@link java.text.SimpleDateFormat} * @return a string representation of this date. * @see java.text.SimpleDateFormat * @since 1.5.7 */ public static String format(Date self, String format) { return new SimpleDateFormat(format).format(self); } /** *

Create a String representation of this date according to the given * format pattern and timezone. *

*

For example: * * def d = new Date(0) * def tz = TimeZone.getTimeZone('GMT') * println d.format('dd/MMM/yyyy', tz) * would return the string * "01/Jan/1970". See documentation for {@link java.text.SimpleDateFormat} * for format pattern use. *

*

Note that a new DateFormat instance is created for every * invocation of this method (for thread safety). * * @param self a Date * @param format the format pattern to use according to {@link java.text.SimpleDateFormat} * @param tz the TimeZone to use * @return a string representation of this date. * @see java.text.SimpleDateFormat * @since 1.8.3 */ public static String format(Date self, String format, TimeZone tz) { SimpleDateFormat sdf = new SimpleDateFormat(format); sdf.setTimeZone(tz); return sdf.format(self); } /** *

Return a string representation of the 'day' portion of this date * according to the locale-specific {@link java.text.DateFormat#SHORT} default format. * For an "en_UK" system locale, this would be dd/MM/yy. *

*

Note that a new DateFormat instance is created for every * invocation of this method (for thread safety). * * @param self a Date * @return a string representation of this date * @see java.text.DateFormat#getDateInstance(int) * @see java.text.DateFormat#SHORT * @since 1.5.7 */ public static String getDateString(Date self) { return DateFormat.getDateInstance(DateFormat.SHORT).format(self); } /** *

Return a string representation of the time portion of this date * according to the locale-specific {@link java.text.DateFormat#MEDIUM} default format. * For an "en_UK" system locale, this would be HH:MM:ss. *

*

Note that a new DateFormat instance is created for every * invocation of this method (for thread safety). * * @param self a Date * @return a string representing the time portion of this date * @see java.text.DateFormat#getTimeInstance(int) * @see java.text.DateFormat#MEDIUM * @since 1.5.7 */ public static String getTimeString(Date self) { return DateFormat.getTimeInstance(DateFormat.MEDIUM).format(self); } /** *

Return a string representation of the date and time time portion of * this Date instance, according to the locale-specific format used by * {@link java.text.DateFormat}. This method uses the {@link java.text.DateFormat#SHORT} * preset for the day portion and {@link java.text.DateFormat#MEDIUM} for the time * portion of the output string. *

*

Note that a new DateFormat instance is created for every * invocation of this method (for thread safety). * * @param self a Date * @return a string representation of this date and time * @see java.text.DateFormat#getDateTimeInstance(int, int) * @since 1.5.7 */ public static String getDateTimeString(Date self) { return DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM).format(self); } /** * Common code for {@link #clearTime(java.util.Calendar)} and {@link #clearTime(java.util.Date)} * and {@link #clearTime(java.sql.Date)} * * @param self a Calendar to adjust */ private static void clearTimeCommon(final Calendar self) { self.set(Calendar.HOUR_OF_DAY, 0); self.clear(Calendar.MINUTE); self.clear(Calendar.SECOND); self.clear(Calendar.MILLISECOND); } /** * Clears the time portion of this Date instance; useful utility where * it makes sense to compare month/day/year only portions of a Date. * * @param self a Date * @return the Date but with the time portion cleared * @since 1.6.7 */ public static Date clearTime(final Date self) { Calendar calendar = Calendar.getInstance(); calendar.setTime(self); clearTimeCommon(calendar); self.setTime(calendar.getTime().getTime()); return self; } /** * Clears the time portion of this java.sql.Date instance; useful utility * where it makes sense to compare month/day/year only portions of a Date. * * @param self a java.sql.Date * @return the java.sql.Date but with the time portion cleared * @since 1.6.7 */ public static java.sql.Date clearTime(final java.sql.Date self) { Calendar calendar = Calendar.getInstance(); calendar.setTime(self); clearTimeCommon(calendar); self.setTime(calendar.getTime().getTime()); return self; } /** * Clears the time portion of this Calendar instance; useful utility * where it makes sense to compare month/day/year only portions of a Calendar. * * @param self a Calendar * @return the Calendar but with the time portion cleared * @since 1.6.7 */ public static Calendar clearTime(final Calendar self) { clearTimeCommon(self); return self; } /** *

Shortcut for {@link java.text.SimpleDateFormat} to output a String representation * of this calendar instance. This method respects the Calendar's assigned * {@link java.util.TimeZone}, whereas calling cal.time.format('HH:mm:ss') * would use the system timezone. *

Note that Calendar equivalents of date.getDateString() * and variants do not exist because those methods are Locale-dependent. * Although a Calendar may be assigned a {@link java.util.Locale}, that information is * lost and therefore cannot be used to control the default date/time formats * provided by these methods. Instead, the system Locale would always be * used. The alternative is to simply call * {@link java.text.DateFormat#getDateInstance(int, java.util.Locale)} and pass the same Locale * that was used for the Calendar. * * @param self this calendar * @param pattern format pattern * @return String representation of this calendar with the given format. * @see java.text.DateFormat#setTimeZone(java.util.TimeZone) * @see java.text.SimpleDateFormat#format(java.util.Date) * @see #format(java.util.Date, String) * @since 1.6.0 */ public static String format(Calendar self, String pattern) { SimpleDateFormat sdf = new SimpleDateFormat(pattern); sdf.setTimeZone(self.getTimeZone()); return sdf.format(self.getTime()); } /** * Iterates from this date up to the given date, inclusive, * incrementing by one day each time. * * @param self a Date * @param to another Date to go up to * @param closure the closure to call * @since 2.2 */ public static void upto(Date self, Date to, Closure closure) { if (self.compareTo(to) <= 0) { for (Date i = (Date) self.clone(); i.compareTo(to) <= 0; i = next(i)) { closure.call(i); } } else throw new GroovyRuntimeException("The argument (" + to + ") to upto() cannot be earlier than the value (" + self + ") it's called on."); } /** * Iterates from the date represented by this calendar up to the date represented * by the given calendar, inclusive, incrementing by one day each time. * * @param self a Calendar * @param to another Calendar to go up to * @param closure the closure to call * @since 2.2 */ public static void upto(Calendar self, Calendar to, Closure closure) { if (self.compareTo(to) <= 0) { for (Calendar i = (Calendar) self.clone(); i.compareTo(to) <= 0; i = next(i)) { closure.call(i); } } else throw new GroovyRuntimeException("The argument (" + to + ") to upto() cannot be earlier than the value (" + self + ") it's called on."); } /** * Iterates from this date down to the given date, inclusive, * decrementing by one day each time. * * @param self a Date * @param to another Date to go down to * @param closure the closure to call * @since 2.2 */ public static void downto(Date self, Date to, Closure closure) { if (self.compareTo(to) >= 0) { for (Date i = (Date) self.clone(); i.compareTo(to) >= 0; i = previous(i)) { closure.call(i); } } else throw new GroovyRuntimeException("The argument (" + to + ") to downto() cannot be later than the value (" + self + ") it's called on."); } /** * Iterates from the date represented by this calendar up to the date represented * by the given calendar, inclusive, incrementing by one day each time. * * @param self a Calendar * @param to another Calendar to go down to * @param closure the closure to call * @since 2.2 */ public static void downto(Calendar self, Calendar to, Closure closure) { if (self.compareTo(to) >= 0) { for (Calendar i = (Calendar) self.clone(); i.compareTo(to) >= 0; i = previous(i)) { closure.call(i); } } else throw new GroovyRuntimeException("The argument (" + to + ") to downto() cannot be later than the value (" + self + ") it's called on."); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy