org.everit.jira.timetracker.plugin.util.DateTimeConverterUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.everit.jira.timetracker.plugin.util.DateTimeConverterUtil.java

Source

/*
 * Copyright (C) 2011 Everit Kft. (http://www.everit.org)
 *
 * 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 org.everit.jira.timetracker.plugin.util;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.DateFormatSymbols;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.everit.jira.core.impl.DateTimeServer;
import org.everit.jira.core.impl.WorklogComponent;
import org.everit.jira.core.util.TimetrackerUtil;
import org.everit.jira.timetracker.plugin.DurationFormatter;
import org.everit.jira.timetracker.plugin.exception.WorklogException;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;

import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.config.properties.APKeys;
import com.atlassian.jira.config.properties.ApplicationProperties;
import com.atlassian.jira.datetime.DateTimeFormatter;
import com.atlassian.jira.datetime.DateTimeFormatterFactory;
import com.atlassian.jira.datetime.DateTimeStyle;
import com.atlassian.jira.security.JiraAuthenticationContext;

/**
 * The utility class of date and time conversions.
 */
public final class DateTimeConverterUtil {

    /**
     * The begin of year.
     */
    public static final int BEGIN_OF_YEAR = 1900;

    /**
     * The date time format.
     */
    public static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm";

    /**
     * The number of days per week.
     */
    public static final int DAYS_PER_WEEK = 7;

    /**
     * The fix date time format for exclude and include dates.
     */
    public static final String FIX_DATE_TIME_FORMAT = "yyyy-MM-dd";

    /**
     * The fix date time format for duration value.
     */
    private static final String FIX_TIME_FORMAT = "HH:mm";

    /**
     * The hour eight.
     */
    public static final int HOUR_EIGHT = 8;

    private static final int HOURS_GROUP = 8;

    private static final int HOURS_GROUP_2 = 2;

    /**
     * The number of hours in day.
     */
    public static final int HOURS_IN_DAY = 24;

    /**
     * The JIRA duration pattern.
     */
    public static final String JIRA_DURATION_PATTERN = "(([01]?[0-9]|2[0-3])[h]*[\\s]+(([0-9]{1,3}|"
            + "1[0-3][0-9]{2}|14[0-3][0-9])[m])*)|"
            + "(([0-9]{1,3}|1[0-3][0-9]{2}|14[0-3][0-9])[m])+|(([01]?[0-9]|2[0-3])[h])+";

    private static final int MILLISEC_IN_SECOND = 1000;

    /**
     * The number of milliseconds per seconds.
     */
    public static final int MILLISECONDS_PER_SECOND = 1000;

    /**
     * The number of mins in quater.
     */
    public static final int MINS_IN_QUATER = 15;

    private static final int MINUTES_GROUP = 6;

    private static final int MINUTES_GROUP_2 = 4;

    /**
     * The number of minutes per hour.
     */
    public static final int MINUTES_PER_HOUR = 60;

    /**
     * The number of quaters in hour.
     */
    public static final int QUATERS_IN_HOUR = 4;

    /**
     * The number of seconds per minute.
     */
    public static final int SECONDS_PER_MINUTE = 60;

    /**
     * The 24 hours pattern.
     */
    public static final String TIME24HOURS_PATTERN = "([01]?[0-9]|2[0-3]):[0-5][0-9]";

    private static final int YEAR_1900 = 1900;

    /**
     * Convert the Timestamp to system timezone, cahnge the Timezone o user timezone and convert back
     * to a new Timestamp.
     *
     * @param systemTimestamp
     *          The original Timesatamp in system TimeZone.
     * @return The new Timestamp in user TimeZone.
     */
    public static Timestamp addTimeZoneToTimestamp(final Timestamp systemTimestamp) {
        if (systemTimestamp == null) {
            return null;
        }
        DateTimeServer converter = DateTimeServer.getInstanceBasedOnSystemTimeZone(systemTimestamp.getTime());
        return new Timestamp(converter.getUserTimeZoneDate().getTime());
    }

    /**
     * Convert joda DateTime to java Date. Convert the date and time without Time Zone correction.
     * (the joda DateTime toDate metod add the time zone).
     *
     * @param dateTime
     *          The dateTime.
     * @return The new date.
     */
    @SuppressWarnings("deprecation")
    public static Date convertDateTimeToDate(final DateTime dateTime) {
        return new Date(dateTime.getYear() - YEAR_1900, dateTime.getMonthOfYear() - 1, dateTime.getDayOfMonth(),
                dateTime.getHourOfDay(), dateTime.getMinuteOfHour(), dateTime.getSecondOfMinute());
    }

    /**
     * Convert the give date to the system TimeZone.
     *
     * @param date
     *          The origonal date
     * @return The date in the System TimeZone.
     */
    public static DateTime convertDateZoneToSystemTimeZone(final DateTime date) {
        DateTime inSystemTimeZone = date.withZone(TimetrackerUtil.getSystemTimeZone());
        return inSystemTimeZone;
    }

    /**
     * Convert the give date to the user TimeZone.
     *
     * @param date
     *          The origonal date
     * @return The date in the User TimeZone.
     */
    public static DateTime convertDateZoneToUserTimeZone(final DateTime date) {
        DateTime inUserTimeZone = date.withZone(TimetrackerUtil.getLoggedUserTimeZone());
        return inUserTimeZone;
    }

    /**
     * Count the worklog end time.
     *
     * @param start
     *          When start the worklog.
     * @param spentMilliseconds
     *          The spent time in milliseconds.
     * @return The string format of the end time.
     * @throws IllegalArgumentException
     *           When can't parse the time.
     */
    public static String countEndTime(final String start, final long spentMilliseconds)
            throws IllegalArgumentException {
        long startMillisecond = DateTimeConverterUtil.stringTimeToDateTime(start).getTime();
        long endMillisecond = startMillisecond + spentMilliseconds;
        return DateTimeConverterUtil.dateTimeToString(new Date(endMillisecond));
    }

    /**
     * Convert date to string use the {@link APKeys#JIRA_LF_DATE_COMPLETE}.
     *
     * @param dateAndTime
     *          The date to convert.
     * @return The result String.
     */
    public static String dateAndTimeToString(final Date dateAndTime) {
        String dateTimeFormat = DateTimeConverterUtil
                .getJiraDefaultDateAndTimeJavaFormat(APKeys.JIRA_LF_DATE_COMPLETE);
        DateFormat formatterDateAndTime = new SimpleDateFormat(dateTimeFormat,
                DateTimeConverterUtil.getLoggedUserLocal());
        String stringDateAndTime = formatterDateAndTime.format(dateAndTime);
        return stringDateAndTime;
    }

    /**
     * Convert the date time to string ({@link DateTimeStyle#TIME}).
     *
     * @param date
     *          The time to convert.
     * @return The result string.
     */
    public static String dateTimeToString(final Date date) {
        DateTimeFormatter dateTimeTimeFormatter = DateTimeConverterUtil.getDateTimeTimeFormatter();
        return dateTimeTimeFormatter.format(date);
    }

    /**
     * Convert the date time to string with ({@link FIX_TIME_FORMAT}).
     *
     * @param date
     *          The time to convert.
     * @return The result string.
     */
    public static String dateTimeToStringWithFixFormat(final Date date) {
        DateFormat formatterDate = new SimpleDateFormat(FIX_TIME_FORMAT);
        formatterDate.setTimeZone(TimeZone.getTimeZone("UTC"));
        return formatterDate.format(date);
    }

    /**
     * Convert the date to String use the fix date format "YYYY-MM-DD".
     *
     * @param date
     *          The Date to convert.
     * @return The result time.
     */
    public static String dateToFixFormatString(final DateTime date) {
        org.joda.time.format.DateTimeFormatter formatterDate = DateTimeFormat.forPattern(FIX_DATE_TIME_FORMAT);
        String dateString = formatterDate.print(date);
        return dateString;
    }

    /**
     * Convert the date to String use the {@link APKeys#JIRA_LF_DATE_DMY}.
     *
     * @param date
     *          The Date to convert.
     * @return The result time.
     */
    public static String dateToString(final Date date) {
        String dateFormat = DateTimeConverterUtil.getJiraDefaultDateAndTimeJavaFormat(APKeys.JIRA_LF_DATE_DMY);
        DateFormat formatterDate = new SimpleDateFormat(dateFormat, DateTimeConverterUtil.getLoggedUserLocal());
        String dateString = formatterDate.format(date);
        return dateString;
    }

    /**
     * Convert String to Date use the fix date format "YYYY-MM-DD".
     *
     * @param dateString
     *          The String date to convert.
     * @return The result Date.
     * @throws ParseException
     *           If can't parse the date.
     */
    public static Date fixFormatStringToDate(final String dateString) throws ParseException {
        DateFormat formatterDate = new SimpleDateFormat(FIX_DATE_TIME_FORMAT);
        formatterDate.setTimeZone(TimeZone.getTimeZone("UTC"));
        Date date = formatterDate.parse(dateString);
        return date;
    }

    /**
     * Convert String to Date use the fix date format "YYYY-MM-DD".
     *
     * @param dateString
     *          The String date to convert.
     * @return The result Date.
     * @throws ParseException
     *           If can't parse the date and the date contains invalid value e.g. 15 as month.
     */
    public static Date fixFormatStringToDateWithValidation(final String dateString) throws ParseException {
        DateFormat formatterDate = new SimpleDateFormat(FIX_DATE_TIME_FORMAT);
        formatterDate.setTimeZone(TimeZone.getTimeZone("UTC"));
        Date date = formatterDate.parse(dateString);
        if (!dateString.equals(formatterDate.format(date))) {
            throw new ParseException("Invalid date value:" + dateString, 0);
        }
        return date;
    }

    /**
     * Get the difference between to date in seconds.
     *
     * @param firstDate
     *          The fisrt date.
     * @param secondDate
     *          The second date.
     * @return The difference between dates.
     */
    public static long getDateDifference(final Date firstDate, final Date secondDate) {
        long diffInMillies = secondDate.getTime() - firstDate.getTime();
        return TimeUnit.SECONDS.convert(diffInMillies, TimeUnit.MILLISECONDS);
    }

    private static DateTimeFormatter getDateTimeTimeFormatter() {
        DateTimeFormatterFactory dateTimeFormatterFactory = ComponentAccessor
                .getComponent(DateTimeFormatterFactory.class);
        return dateTimeFormatterFactory.formatter().forLoggedInUser().withSystemZone()
                .withStyle(DateTimeStyle.TIME);
    }

    private static String getJiraDefaultDateAndTimeJavaFormat(final String formatKey) {
        ApplicationProperties applicationProperties = ComponentAccessor.getComponent(ApplicationProperties.class);
        return applicationProperties.getDefaultBackedString(formatKey);
    }

    private static Locale getLoggedUserLocal() {
        JiraAuthenticationContext authenticationContext = ComponentAccessor.getJiraAuthenticationContext();
        return authenticationContext.getI18nHelper().getLocale();
    }

    /**
     * Check the Time is valid to the {@value #JIRA_DURATION_PATTERN} pattern.
     *
     * @param time
     *          The time to validate.
     * @return If valid then true else false.
     */
    public static boolean isValidJiraTime(final String time) {
        return Pattern.matches(JIRA_DURATION_PATTERN, time);
    }

    /**
     * Check the Time is valid to the {@value #TIME24HOURS_PATTERN} pattern.
     *
     * @param time
     *          The time to validate.
     * @return If valid then true else false.
     */
    public static boolean isValidTime(final String time) {
        boolean match24Format = Pattern.matches(TIME24HOURS_PATTERN, time);
        StringBuilder sb = new StringBuilder();
        sb.append("^([01]?[0-9]|2[0-3]):[0-5][0-9]( (");
        Locale locale = DateTimeConverterUtil.getLoggedUserLocal();
        DateFormatSymbols dateFormatSymbols = new DateFormatSymbols(locale);
        String[] amPmStrings = dateFormatSymbols.getAmPmStrings();
        int index = 0;
        for (String string : amPmStrings) {
            sb.append(string + "|");
            sb.append(string.toLowerCase(locale));
            if (index < (amPmStrings.length - 1)) {
                sb.append("|");
            }
            index++;
        }
        sb.append("))$");
        boolean matchAmPmFormat = Pattern.matches(sb.toString(), time);
        return match24Format || matchAmPmFormat;

    }

    /**
     * Converts JIRA duration style strings to seconds.
     *
     * @param duration
     *          JIRA duration style string
     * @return The calculated seconds.
     */
    public static int jiraDurationToSeconds(final String duration) {
        Pattern durPatt = Pattern.compile(DateTimeConverterUtil.JIRA_DURATION_PATTERN);
        Matcher m = durPatt.matcher(duration);
        int seconds = 0;
        if (m.matches()) {
            if (m.group(HOURS_GROUP) != null) {
                seconds = Integer.parseInt(m.group(HOURS_GROUP)) * DateTimeConverterUtil.MINUTES_PER_HOUR
                        * DateTimeConverterUtil.SECONDS_PER_MINUTE;
            } else if (m.group(MINUTES_GROUP) != null) {
                seconds = Integer.parseInt(m.group(MINUTES_GROUP)) * DateTimeConverterUtil.SECONDS_PER_MINUTE;
            } else if ((m.group(HOURS_GROUP_2) != null) && (m.group(MINUTES_GROUP_2) != null)) {
                seconds = Integer.parseInt(m.group(HOURS_GROUP_2)) * DateTimeConverterUtil.MINUTES_PER_HOUR
                        * DateTimeConverterUtil.SECONDS_PER_MINUTE;
                seconds += Integer.parseInt(m.group(MINUTES_GROUP_2)) * DateTimeConverterUtil.SECONDS_PER_MINUTE;
            }
        }
        return seconds;
    }

    /**
     * Return a Calendar with time set by the start of the given day.
     *
     * @param date
     *          The time to set the calendar
     * @return The calendar which represents the start of the day
     */
    public static DateTime setDateToDayStart(final DateTime date) {
        DateTime dateStartOfTheDay = date.withHourOfDay(0);
        dateStartOfTheDay = dateStartOfTheDay.withMinuteOfHour(0);
        dateStartOfTheDay = dateStartOfTheDay.withSecondOfMinute(0);
        dateStartOfTheDay = dateStartOfTheDay.withMillisOfSecond(0);
        return dateStartOfTheDay;
    }

    /**
     * Convert String ({@value DateTimeStyle#TIME}) to Time.
     *
     * @param time
     *          The String time.
     * @return The result date.
     */
    public static Date stringTimeToDateTime(final String time) throws IllegalArgumentException {
        DateTimeFormatter dateTimeTimeFormatter = DateTimeConverterUtil.getDateTimeTimeFormatter();
        return dateTimeTimeFormatter.parse(time);
    }

    /**
     * Convert String with ({@value FIX_TIME_FORMAT}) to Time.
     *
     * @param time
     *          The String time.
     * @return The result date.
     * @throws ParseException
     *           If can't parse the date.
     */
    public static Date stringTimeToDateTimeWithFixFormat(final String time) throws ParseException {
        DateFormat formatterDate = new SimpleDateFormat(FIX_TIME_FORMAT);
        formatterDate.setTimeZone(TimeZone.getTimeZone("UTC"));
        return formatterDate.parse(time);
    }

    /**
     * Covert String time (hh:mm) to jira format (1h 30m) String. Use the
     * {@link DateTimeConverterUtil} methods.
     *
     * @param time
     *          The time.
     * @return The new formated String.
     * @throws ParseException
     *           If can't parse the date.
     */
    public static String stringTimeToString(final String time) throws ParseException {
        long seconds = DateTimeConverterUtil.stringTimeToDateTimeWithFixFormat(time).getTime() / MILLISEC_IN_SECOND;
        String result = new DurationFormatter().exactDuration(seconds);
        return result;
    }

    /**
     * Convert String to Date use the {@link APKeys#JIRA_LF_DATE_DMY}.
     *
     * @param dateString
     *          The String date to convert.
     * @return The result Date.
     * @throws ParseException
     *           If can't parse the date.
     */
    public static Date stringToDate(final String dateString) throws ParseException {
        String dateFormat = DateTimeConverterUtil.getJiraDefaultDateAndTimeJavaFormat(APKeys.JIRA_LF_DATE_DMY);
        DateFormat formatterDate = new SimpleDateFormat(dateFormat, DateTimeConverterUtil.getLoggedUserLocal());
        Date date = formatterDate.parse(dateString);
        return date;
    }

    /**
     * Convert String to date and time and merge them. Use the stringToDate and stringTimeToDateTime
     * methods.
     *
     * @param date
     *          The date.
     * @param time
     *          The time.
     * @return The result Date.
     */
    public static Date stringToDateAndTime(final Date date, final Date time) {
        Calendar dateCalendaer = Calendar.getInstance();
        dateCalendaer.setTime(date);
        Calendar timeCalendar = Calendar.getInstance();
        timeCalendar.setTime(time);
        dateCalendaer.set(Calendar.HOUR_OF_DAY, timeCalendar.get(Calendar.HOUR_OF_DAY));
        dateCalendaer.set(Calendar.MINUTE, timeCalendar.get(Calendar.MINUTE));
        return dateCalendaer.getTime();
    }

    /**
     * Convert String to date and time and merge them. Use the stringToDate and stringTimeToDateTime
     * methods.
     *
     * @param date
     *          The date.
     * @param timeString
     *          The time string to convert.
     * @return The result Date.
     */
    public static Date stringToDateAndTime(final Date date, final String timeString)
            throws IllegalArgumentException {
        return DateTimeConverterUtil.stringToDateAndTime(date,
                DateTimeConverterUtil.stringTimeToDateTime(timeString));
    }

    /**
     * Concat DateTime date and Date time to a DateTime date based on the originalDate param.
     *
     * @param originalDate
     *          The date.
     * @param time
     *          The time.
     * @return The concated date time.
     */
    public static DateTime stringToDateAndTime(final DateTime originalDate, final Date time) {
        DateTime date;
        try {
            date = originalDate.withHourOfDay(time.getHours());
            date = date.withMinuteOfHour(time.getMinutes());
        } catch (IllegalArgumentException e) {
            throw new WorklogException(WorklogComponent.PropertiesKey.DATE_PARSE, originalDate + " " + time);
        }
        return date;
    }

    /**
     * Concat DateTime date and String time to a DateTime date based on the originalDate param.
     *
     * @param originalDate
     *          The date.
     * @param time
     *          The time.
     * @return The concated date time.
     */
    public static DateTime stringToDateAndTime(final DateTime originalDate, final String time) {
        Date timeDate;
        DateTime date;
        try {
            timeDate = DateTimeConverterUtil.stringTimeToDateTime(time);
            date = DateTimeConverterUtil.stringToDateAndTime(originalDate, timeDate);
        } catch (IllegalArgumentException e) {
            throw new WorklogException(WorklogComponent.PropertiesKey.DATE_PARSE, originalDate + " " + time);
        }
        return date;
    }

    /**
     * Convert String ({@value #DATE_TIME_FORMAT}) to date and time.
     *
     * @param dateAndTimeString
     *          The date time string to convert.
     * @return The result Date.
     * @throws ParseException
     *           if can't parse the date.
     */
    public static Date stringToDateAndTime(final String dateAndTimeString) throws ParseException {
        DateFormat formatterDateAndTime = new SimpleDateFormat(DATE_TIME_FORMAT,
                DateTimeConverterUtil.getLoggedUserLocal());
        Date date = formatterDateAndTime.parse(dateAndTimeString);
        return date;
    }

    /**
     * Private constructor.
     */
    private DateTimeConverterUtil() {
    }

}