/* * Copyright 2012 Kazumune Katagiri. (http://d.hatena.ne.jp/nemuzuka) * * Licensed 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 jp.co.nemuzuka.utils; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.TimeZone; import jp.co.nemuzuka.core.entity.UserTimeZone; import org.apache.commons.lang.StringUtils; /** * 日付・時刻関連のUtils. * @author k-katagiri */ public class DateTimeUtils { /** 日曜日. */ public static final String SUNDAY = "sunday"; /** 月曜日. */ public static final String MONDAY = "monday"; /** 火曜日. */ public static final String TUESDAY = "tuesday"; /** 水曜日. */ public static final String WEDNESDAY = "wednesday"; /** 木曜日. */ public static final String THURSDAY = "thursday"; /** 金曜日. */ public static final String FRIDAY = "friday"; /** 土曜日. */ public static final String SATURDAY = "saturday"; /** * 月初・月末取得. * 引数の作成対象年月より、月初と月末のDateオブジェクトを作成します。 * @param targetYyyyMM 作成対象月 * @return index 0:月初のDate index 1:月末のDate */ public static List<Date> getStartEndDate(String targetYyyyMM) { SimpleDateFormat sdf = createSdf("yyyyMMdd"); sdf.setLenient(false); List<Date> retList = new ArrayList<Date>(); try { Date startDate = sdf.parse(targetYyyyMM + "01"); retList.add(startDate); //1月追加して、1日戻したものが月末 Date endDate = addMonths(startDate, 1); endDate = addDays(endDate, -1); retList.add(endDate); } catch (ParseException e) { throw new RuntimeException(e); } return retList; } /** * 月初~月末List取得. * 引数の作成対象年月より、月初~月末のDateオブジェクトListを作成します。 * @param targetYyyyMM 作成対象年月 * @return 月初~月末List */ public static List<Date> getStartEndDateList(String targetYyyyMM) { List<Date> startEndList = getStartEndDate(targetYyyyMM); return createDateList(startEndList.get(0), startEndList.get(1)); } /** * 月初・月末取得. * 引数の作成対象年月より、月初と月末のDateオブジェクトを作成します。 * ただし、月初が日曜日でない場合、直前の日曜日まで日付を移動し、 * 月末が土曜日で無い場合、直後の土曜日まで日付を移動します。 * @param targetYyyyMM 作成対象年月日 * @return index 0:月初のDate index 1:月末のDate */ public static List<Date> getStartEndDate4SunDay(String targetYyyyMM) { List<Date> list = getStartEndDate(targetYyyyMM); Date startDate = list.get(0); Calendar calendar = Calendar.getInstance(); calendar.setTimeZone(getTimeZone()); //月初の設定 while(true) { calendar.setTime(startDate); if(calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) { //対象日が日曜日の場合、ループを抜ける break; } //1日前に戻る startDate = addDays(startDate, -1); } Date endDate = list.get(1); //月末の設定 while(true) { calendar.setTime(endDate); if(calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) { //対象日が土曜日の場合、ループを抜ける break; } //1日進める endDate = addDays(endDate, 1); } List<Date> retList = new ArrayList<Date>(); retList.add(startDate); retList.add(endDate); return retList; } /** * 月初~月末List取得. * 引数の作成対象年月より、月初~月末のDateオブジェクトListを作成します。 * ただし、月初が日曜日でない場合、直前の日曜日まで日付を移動し、 * 月末が土曜日で無い場合、直後の土曜日まで日付を移動します。 * @param targetYyyyMM 作成対象年月 * @return 月初~月末List */ public static List<Date> getStartEndDate4SunDayList(String targetYyyyMM) { List<Date> startEndList = getStartEndDate4SunDay(targetYyyyMM); return createDateList(startEndList.get(0), startEndList.get(1)); } /** * 対象日の月末日を取得します。 * @param targetDate 取得対象日 * @param cal Calendarインスタンス * @return 月末日 */ public static int getLastDay(Date targetDate, Calendar cal) { cal.setTime(targetDate); return cal.getActualMaximum(Calendar.DATE); } /** * 時間加算. * 引数の時分文字列に指定した分を加算して、その結果の文字列を返却します。 * @param targethhmm 対象文字列(HHmmフォーマット) * @param time 加算時刻(分単位) * @return 加算後文字列 */ public static String addTime(String targethhmm, int time) { SimpleDateFormat sdf = createSdf("HHmm"); Date date = null; try { date = sdf.parse(targethhmm); } catch (ParseException e) { throw new RuntimeException(e); } date = addMinutes(date, time); return sdf.format(date); } /** * システム日付の翌月の文字列を返却します。 * @return システム日付の翌月(yyyyMM形式) */ public static String getNextMonth() { //システム日付から1ヶ月加算 Date date = CurrentDateUtils.getInstance().getCurrentDate(); date = addMonths(date, 1); SimpleDateFormat sdf = createSdf("yyyyMM"); return sdf.format(date); } /** * 月加算. * 引数より指定月数を加算します。 * @param targetYyyyMm 対象年月(yyyyMM形式) * @param amount 移動月数(負数の場合、過去に戻る) * @return 加算後の年月(yyyyMM形式) */ public static String addMonth(String targetYyyyMm, int amount) { SimpleDateFormat sdf = createSdf("yyyyMMdd"); Date date; try { date = sdf.parse(targetYyyyMm + "01"); } catch (ParseException e) { throw new RuntimeException(e); } date = addMonths(date, amount); SimpleDateFormat sdf2 = createSdf("yyyyMM"); return sdf2.format(date); } /** * システム日付の文字列を返却します。 * @return システム日付(yyyyMM形式) */ public static String getMonth() { Date date = CurrentDateUtils.getInstance().getCurrentDate(); SimpleDateFormat sdf = createSdf("yyyyMM"); return sdf.format(date); } /** * 日数計算. * 開始日から終了日まで何日あるかを返却します。 * 開始日 = 終了日の場合、1日を返却します。 * @param startDate 開始日 * @param endDate 終了日 * @return 開始日から終了日までの日数 */ public static int getDays(Date startDate, Date endDate) { if(startDate.getTime() > endDate.getTime()) { //開始日 > 終了日の場合、不正データとしてエラーにする throw new RuntimeException(); } Date targetDate = startDate; int days = 1; while(true) { if(targetDate.getTime() >= endDate.getTime()) { break; } targetDate = addDays(targetDate, 1); days++; } return days; } /** * 範囲チェック. * 対象となる時刻が、基準となる時刻に被るかチェックします。 * From <= Toの関係であることが前提条件です。 * @param baseFrom 基準From(HHmm形式) * @param baseTo 基準To(HHmm形式) * @param targetFrom 対象From(HHmm形式) * @param targetTo 対象To(HHmm形式) * @return 被る場合、true */ public static boolean rangeCheck(String baseFrom, String baseTo, String targetFrom, String targetTo) { if( DateTimeChecker.isHourMinute(baseFrom) == false || DateTimeChecker.isHourMinute(baseTo) == false || DateTimeChecker.isHourMinute(baseFrom) == false || DateTimeChecker.isHourMinute(baseTo) == false ){ return false; } int baseFromNum = Integer.valueOf(baseFrom); int baseToNum = Integer.valueOf(baseTo); int targetFromNum = Integer.valueOf(targetFrom); int targetToNum = Integer.valueOf(targetTo); if(baseFromNum > baseToNum || targetFromNum > targetToNum) { return false; } //基準の開始が対象From~対象Toの間に含まれる場合 if(targetFromNum <= baseFromNum && baseFromNum < targetToNum) { return true; } //基準の終了が対象From~対象Toの間に含まれる場合 if(targetFromNum < baseToNum && baseToNum <= targetToNum) { return true; } //基準の範囲内に収まる場合 if(baseFromNum <= targetFromNum && targetFromNum <= baseToNum && baseFromNum <= targetToNum && targetToNum <= baseToNum) { return true; } return false; } /** * 日付List生成. * 開始日から終了日までの日付Listを作成します。 * @param startDate 開始日 * @param endDate 終了日 * @return 生成日付List */ public static List<Date> createDateList(Date startDate, Date endDate) { List<Date> retList = new ArrayList<Date>(); Date addTargetDate = startDate; Date endTargetDate = endDate; while(true) { retList.add(addTargetDate); addTargetDate = addDays(addTargetDate, 1); if(addTargetDate.getTime() > endTargetDate.getTime()) { //月末の日付を超えた場合、ループを抜ける break; } } return retList; } /** * 分換算. * 時間を分に換算します。 * @param targetHhMm 換算元時刻(HHmmフォーマット) * @return 換算分 */ public static int convertMinute(String targetHhMm) { String hour = targetHhMm.substring(0, 2); String min = targetHhMm.substring(2); int hourInt = Integer.parseInt(hour); int minInt = Integer.parseInt(min); return hourInt * 60 + minInt; } /** * 差分算出. * 引数の2つの時刻の経過分を算出します * @param fromHhMm from時刻 * @param toHhMm to時刻 * @return 経過分 */ public static int calcMin(String fromHhMm, String toHhMm) { int fromInt = convertMinute(fromHhMm); int toInt = convertMinute(toHhMm); return toInt - fromInt; } /** * 引数の日付が何番目のListに格納するかを取得します。 * @param targetDate 取得対象日付 * @param dateList 検索日付List * @return index(該当無しの場合、-1) */ public static int getListIndex(Date targetDate, List<Date> dateList) { int index = 0; boolean isBreak = false; for(Date target : dateList) { if(target.getTime() == targetDate.getTime()) { isBreak = true; break; } index++; } if(isBreak) { return index; } return -1; } /** * 時刻フォーマット. * @param time 設定元時刻(HHmmフォーマット) * @return フォーマット済み時刻 */ public static String formatTime(String time) { String hh = time.substring(0, 2); String mm = time.substring(2); return hh + ":" + mm; } /** * 年齢算出. * 生年月日と基準日を元に年齢を算出します。 * @param birthDay 生年月日 * @param baseDate 基準日 * @return 年齢 */ public static int calcAge(Date birthDay, Date baseDate) { if(birthDay == null || baseDate == null) { throw new IllegalArgumentException("入力が不正です。"); } SimpleDateFormat sdf = createSdf("yyyyMMdd"); int val1 = Integer.valueOf(sdf.format(baseDate)); int val2 = Integer.valueOf(sdf.format(birthDay)); return (val1 - val2) / 10000; } /** * SimpleDateForm取得. * タイムゾーンをThreadLocalの値にしたSimpleDateFormatを取得します。 * 未設定の場合、JSTを返します。 * @param pattern フォーマットパターン * @return SimpleDateFormatインスタンス */ public static SimpleDateFormat createSdf(String pattern) { SimpleDateFormat sdf = new SimpleDateFormat(pattern); sdf.setTimeZone(getTimeZone()); return sdf; } /** * 月加算. * 引数の日付に月を加算します。 * @param date 日付 * @param amount 増減 * @return 引数の日付に月を変更したもの */ public static Date addMonths(Date date, int amount) { return add(date, Calendar.MONTH, amount); } /** * 日加算. * 引数の日付に日を加算します。 * @param date 日付 * @param amount 増減 * @return 引数の日付に日を変更したもの */ public static Date addDays(Date date, int amount) { return add(date, Calendar.DAY_OF_MONTH, amount); } /** * 週加算. * 引数の日付に週を加算します。 * @param date 日付 * @param amount 増減 * @return 引数の日付に週を変更したもの */ public static Date addWeeks(Date date, int amount) { return add(date, Calendar.WEEK_OF_YEAR, amount); } /** * 分加算. * 引数の日付に分を加算します。 * @param date 日付 * @param amount 増減 * @return 引数の日付に分を変更したもの */ public static Date addMinutes(Date date, int amount) { return add(date, Calendar.MINUTE, amount); } /** * 日付加算. * 対象の日付に対して、タイムゾーンを意識して、日付加算を行います。 * DateUtilsでは、デフォルトのタイムゾーンを使用するので、新しく作成しました。 * @param date 対象日付 * @param calendarField 処理対象 * @param amount 増減 * @return 変更後日付 */ 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(getTimeZone()); c.setTime(date); c.add(calendarField, amount); return c.getTime(); } /** * タイムゾーン取得. * @return ThreadLocalに設定されているタイムゾーン */ private static TimeZone getTimeZone() { String timeZone = UserTimeZone.timeZone.get(); if(StringUtils.isEmpty(timeZone)) { timeZone = jp.co.nemuzuka.common.TimeZone.GMT_P_9.getCode(); } return TimeZone.getTimeZone(timeZone); } }