Here you can find the source of ceiling(Object date, int field)
Ceil this date, leaving the field specified as the most significant field.
For example, if you had the datetime of 28 Mar 2002 13:45:01.231, if you passed with HOUR, it would return 28 Mar 2002 13:00:00.000.
Parameter | Description |
---|---|
date | the date to work with, either Date or Calendar , not null |
field | the field from Calendar or <code>SEMI_MONTH</code> |
Parameter | Description |
---|---|
IllegalArgumentException | if the date is <code>null</code> |
ClassCastException | if the object type is not a Date or Calendar |
ArithmeticException | if the year is over 280 million |
public static Date ceiling(Object date, int field)
/*//from www . j ava2 s . c o m * 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. */ import java.text.ParseException; import java.text.ParsePosition; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.Iterator; import java.util.NoSuchElementException; public class Main{ /** * This is half a month, so this represents whether a date is in the top * or bottom half of the month. */ public static final int SEMI_MONTH = 1001; private static final int[][] fields = { { Calendar.MILLISECOND }, { Calendar.SECOND }, { Calendar.MINUTE }, { Calendar.HOUR_OF_DAY, Calendar.HOUR }, { Calendar.DATE, Calendar.DAY_OF_MONTH, Calendar.AM_PM /* Calendar.DAY_OF_YEAR, Calendar.DAY_OF_WEEK, Calendar.DAY_OF_WEEK_IN_MONTH */ }, { Calendar.MONTH, DateUtils.SEMI_MONTH }, { Calendar.YEAR }, { Calendar.ERA } }; /** * Constant marker for truncating. * @since 3.0 */ private static final int MODIFY_TRUNCATE = 0; /** * Constant marker for rounding. * @since 3.0 */ private static final int MODIFY_ROUND = 1; /** * Constant marker for ceiling. * @since 3.0 */ private static final int MODIFY_CEILING = 2; /** * <p>Ceil this date, leaving the field specified as the most * significant field.</p> * * <p>For example, if you had the datetime of 28 Mar 2002 * 13:45:01.231, if you passed with HOUR, it would return 28 Mar * 2002 14:00:00.000. If this was passed with MONTH, it would * return 1 Apr 2002 0:00:00.000.</p> * * @param date the date to work with, not null * @param field the field from {@code Calendar} or <code>SEMI_MONTH</code> * @return the different ceil date, not null * @throws IllegalArgumentException if the date is <code>null</code> * @throws ArithmeticException if the year is over 280 million * @since 2.5 */ public static Date ceiling(Date date, int field) { if (date == null) { throw new IllegalArgumentException("The date must not be null"); } Calendar gval = Calendar.getInstance(); gval.setTime(date); modify(gval, field, MODIFY_CEILING); return gval.getTime(); } /** * <p>Ceil this date, leaving the field specified as the most * significant field.</p> * * <p>For example, if you had the datetime of 28 Mar 2002 * 13:45:01.231, if you passed with HOUR, it would return 28 Mar * 2002 13:00:00.000. If this was passed with MONTH, it would * return 1 Mar 2002 0:00:00.000.</p> * * @param date the date to work with, not null * @param field the field from {@code Calendar} or <code>SEMI_MONTH</code> * @return the different ceil date, not null * @throws IllegalArgumentException if the date is <code>null</code> * @throws ArithmeticException if the year is over 280 million * @since 2.5 */ public static Calendar ceiling(Calendar date, int field) { if (date == null) { throw new IllegalArgumentException("The date must not be null"); } Calendar ceiled = (Calendar) date.clone(); modify(ceiled, field, MODIFY_CEILING); return ceiled; } /** * <p>Ceil this date, leaving the field specified as the most * significant field.</p> * * <p>For example, if you had the datetime of 28 Mar 2002 * 13:45:01.231, if you passed with HOUR, it would return 28 Mar * 2002 13:00:00.000. If this was passed with MONTH, it would * return 1 Mar 2002 0:00:00.000.</p> * * @param date the date to work with, either {@code Date} or {@code Calendar}, not null * @param field the field from {@code Calendar} or <code>SEMI_MONTH</code> * @return the different ceil date, not null * @throws IllegalArgumentException if the date is <code>null</code> * @throws ClassCastException if the object type is not a {@code Date} or {@code Calendar} * @throws ArithmeticException if the year is over 280 million * @since 2.5 */ public static Date ceiling(Object date, int field) { if (date == null) { throw new IllegalArgumentException("The date must not be null"); } if (date instanceof Date) { return ceiling((Date) date, field); } else if (date instanceof Calendar) { return ceiling((Calendar) date, field).getTime(); } else { throw new ClassCastException( "Could not find ceiling of for type: " + date.getClass()); } } /** * <p>Internal calculation method.</p> * * @param val the calendar, not null * @param field the field constant * @param modType type to truncate, round or ceiling * @throws ArithmeticException if the year is over 280 million */ private static void modify(Calendar val, int field, int modType) { if (val.get(Calendar.YEAR) > 280000000) { throw new ArithmeticException( "Calendar value too large for accurate calculations"); } if (field == Calendar.MILLISECOND) { return; } // ----------------- Fix for LANG-59 ---------------------- START --------------- // see http://issues.apache.org/jira/browse/LANG-59 // // Manually truncate milliseconds, seconds and minutes, rather than using // Calendar methods. Date date = val.getTime(); long time = date.getTime(); boolean done = false; // truncate milliseconds int millisecs = val.get(Calendar.MILLISECOND); if (MODIFY_TRUNCATE == modType || millisecs < 500) { time = time - millisecs; } if (field == Calendar.SECOND) { done = true; } // truncate seconds int seconds = val.get(Calendar.SECOND); if (!done && (MODIFY_TRUNCATE == modType || seconds < 30)) { time = time - (seconds * 1000L); } if (field == Calendar.MINUTE) { done = true; } // truncate minutes int minutes = val.get(Calendar.MINUTE); if (!done && (MODIFY_TRUNCATE == modType || minutes < 30)) { time = time - (minutes * 60000L); } // reset time if (date.getTime() != time) { date.setTime(time); val.setTime(date); } // ----------------- Fix for LANG-59 ----------------------- END ---------------- boolean roundUp = false; for (int[] aField : fields) { for (int element : aField) { if (element == field) { //This is our field... we stop looping if (modType == MODIFY_CEILING || (modType == MODIFY_ROUND && roundUp)) { if (field == DateUtils.SEMI_MONTH) { //This is a special case that's hard to generalize //If the date is 1, we round up to 16, otherwise // we subtract 15 days and add 1 month if (val.get(Calendar.DATE) == 1) { val.add(Calendar.DATE, 15); } else { val.add(Calendar.DATE, -15); val.add(Calendar.MONTH, 1); } // ----------------- Fix for LANG-440 ---------------------- START --------------- } else if (field == Calendar.AM_PM) { // This is a special case // If the time is 0, we round up to 12, otherwise // we subtract 12 hours and add 1 day if (val.get(Calendar.HOUR_OF_DAY) == 0) { val.add(Calendar.HOUR_OF_DAY, 12); } else { val.add(Calendar.HOUR_OF_DAY, -12); val.add(Calendar.DATE, 1); } // ----------------- Fix for LANG-440 ---------------------- END --------------- } else { //We need at add one to this field since the // last number causes us to round up val.add(aField[0], 1); } } return; } } //We have various fields that are not easy roundings int offset = 0; boolean offsetSet = false; //These are special types of fields that require different rounding rules switch (field) { case DateUtils.SEMI_MONTH: if (aField[0] == Calendar.DATE) { //If we're going to drop the DATE field's value, // we want to do this our own way. //We need to subtrace 1 since the date has a minimum of 1 offset = val.get(Calendar.DATE) - 1; //If we're above 15 days adjustment, that means we're in the // bottom half of the month and should stay accordingly. if (offset >= 15) { offset -= 15; } //Record whether we're in the top or bottom half of that range roundUp = offset > 7; offsetSet = true; } break; case Calendar.AM_PM: if (aField[0] == Calendar.HOUR_OF_DAY) { //If we're going to drop the HOUR field's value, // we want to do this our own way. offset = val.get(Calendar.HOUR_OF_DAY); if (offset >= 12) { offset -= 12; } roundUp = offset >= 6; offsetSet = true; } break; } if (!offsetSet) { int min = val.getActualMinimum(aField[0]); int max = val.getActualMaximum(aField[0]); //Calculate the offset from the minimum allowed value offset = val.get(aField[0]) - min; //Set roundUp if this is more than half way between the minimum and maximum roundUp = offset > ((max - min) / 2); } //We need to remove this field if (offset != 0) { val.set(aField[0], val.get(aField[0]) - offset); } } throw new IllegalArgumentException("The field " + field + " is not supported"); } /** * Adds to a date returning a new object. * The original {@code Date} is unchanged. * * @param date the date, not null * @param calendarField the calendar field to add to * @param amount the amount to add, may be negative * @return the new {@code Date} with the amount added * @throws IllegalArgumentException if the date is null */ private static Date add(Date date, int calendarField, int amount) { if (date == null) { throw new IllegalArgumentException("The date must not be null"); } Calendar c = Calendar.getInstance(); c.setTime(date); c.add(calendarField, amount); return c.getTime(); } /** * Sets the specified field to a date returning a new object. * This does not use a lenient calendar. * The original {@code Date} is unchanged. * * @param date the date, not null * @param calendarField the {@code Calendar} field to set the amount to * @param amount the amount to set * @return a new {@code Date} set with the specified value * @throws IllegalArgumentException if the date is null * @since 2.4 */ private static Date set(Date date, int calendarField, int amount) { if (date == null) { throw new IllegalArgumentException("The date must not be null"); } // getInstance() returns a new object, so this method is thread safe. Calendar c = Calendar.getInstance(); c.setLenient(false); c.setTime(date); c.set(calendarField, amount); return c.getTime(); } }