001/*
002 *  Copyright 2017 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.core.util;
017
018import java.time.Duration;
019import java.time.Instant;
020import java.time.LocalDate;
021import java.time.LocalDateTime;
022import java.time.ZoneId;
023import java.time.ZonedDateTime;
024import java.util.Date;
025
026/**
027 * Helper for converting dates from the old ({@link Date}) to the new ({@link java.time}) JDK
028 * Special thanks to http://stackoverflow.com/questions/21242110/convert-java-util-date-to-java-time-localdate#answer-27378709
029 * which inspired this code
030 * 
031 * See also http://stackoverflow.com/questions/19431234/converting-between-java-time-localdatetime-and-java-util-date
032 */
033public final class DateUtils
034{
035    private DateUtils()
036    {
037        // empty
038    }
039    
040    /**
041     * Converts this {@link Date} object to an {@link Instant}.
042     * @param date The date object
043     * @return an instant representing the same point on the time-line as this {@link Date} object
044     */
045    public static Instant asInstant(Date date)
046    {
047        return date == null ? null : date.toInstant();
048    }
049    
050    /**
051     * Converts this {@link Date} object to an {@link Instant}.
052     * @param date The date object
053     * @param zone The zone
054     * @return an instant representing the same point on the time-line as this {@link Date} object
055     */
056    public static ZonedDateTime asZonedDateTime(Date date, ZoneId zone)
057    {
058        return date == null ? null : asInstant(date).atZone(zone != null ? zone : ZoneId.systemDefault());
059    }
060    
061    /**
062     * Converts this {@link Date} object to a {@link LocalDate}.
063     * 
064     * This returns a {@link LocalDate} with the same year, month and day as this {@link Date}.
065     * @param date The date object
066     * @param zone The zone
067     * @return the {@link LocalDate} part of this {@link Date}
068     */
069    public static LocalDate asLocalDate(Date date, ZoneId zone)
070    {
071        return asZonedDateTime(date, zone).toLocalDate();
072    }
073    
074    /**
075     * Converts this {@link Date} object to a {@link LocalDate}.
076     * 
077     * This returns a {@link LocalDate} with the same year, month and day as this {@link Date}.
078     * @param date The date object
079     * @return the {@link LocalDate} part of this {@link Date}
080     */
081    public static LocalDate asLocalDate(Date date)
082    {
083        return asLocalDate(date, ZoneId.systemDefault());
084    }
085    
086    /**
087     * Converts this {@link Date} object to a {@link LocalDateTime}.
088     * 
089     * This returns a {@link LocalDateTime} with the same year, month, day and time as this {@link Date}.
090     * @param date The date object
091     * @param zone The zone
092     * @return the {@link LocalDateTime} part of this {@link Date}
093     */
094    public static LocalDateTime asLocalDateTime(Date date, ZoneId zone)
095    {
096        return asZonedDateTime(date, zone).toLocalDateTime();
097    }
098    
099    /**
100     * Converts this {@link Date} object to a {@link LocalDateTime}.
101     * 
102     * This returns a {@link LocalDateTime} with the same year, month, day and time as this {@link Date}.
103     * @param date The date object
104     * @return the {@link LocalDateTime} part of this {@link Date}
105     */
106    public static LocalDateTime asLocalDateTime(Date date)
107    {
108        return asLocalDateTime(date, ZoneId.systemDefault());
109    }
110    
111    /**
112     * Converts this {@link LocalDate} object to a {@link Date}.
113     * 
114     * @param localDate The local date object
115     * @return the {@link Date} part of this {@link LocalDate}
116     */
117    public static Date asDate(LocalDate localDate)
118    {
119        return asDate(localDate, ZoneId.systemDefault());
120    }
121    
122    /**
123     * Converts this {@link LocalDate} object to a {@link Date}.
124     * 
125     * @param localDate The local date object
126     * @param zone The zone
127     * @return the {@link Date} part of this {@link LocalDate}
128     */
129    public static Date asDate(LocalDate localDate, ZoneId zone)
130    {
131        return Date.from(localDate.atStartOfDay().atZone(zone).toInstant());
132    }
133
134    /**
135     * Converts this {@link LocalDateTime} object to a {@link Date}.
136     * 
137     * @param localDateTime The local date time object
138     * @return the {@link Date} part of this {@link LocalDateTime}
139     */
140    public static Date asDate(LocalDateTime localDateTime)
141    {
142        return asDate(localDateTime, ZoneId.systemDefault());
143    }
144    
145    /**
146     * Converts this {@link LocalDateTime} object to a {@link Date}.
147     * 
148     * @param localDateTime The local date time object
149     * @param zone The zone
150     * @return the {@link Date} part of this {@link LocalDateTime}
151     */
152    public static Date asDate(LocalDateTime localDateTime, ZoneId zone)
153    {
154        return Date.from(localDateTime.atZone(zone).toInstant());
155    }
156    
157    /**
158     * Format a duration for logs
159     * @param duration duration to log
160     * @return a string representing the duration
161     */
162    public static String formatDuration(Duration duration)
163    {
164        return formatDuration(duration.toMillis());
165    }
166    
167    /**
168     * Format a duration for logs
169     * @param duration miliseconds representing the duration
170     * @return a string representing the duration
171     */
172    public static String formatDuration(long duration)
173    {
174        StringBuilder sb = new StringBuilder();
175        long durationCopy = duration;
176        long ms = durationCopy % 1000;
177        durationCopy /= 1000;
178        long s = durationCopy % 60;
179        durationCopy /= 60;
180        long m = durationCopy % 60;
181        durationCopy /= 60;
182        long h = durationCopy % 24;
183        durationCopy /= 24;
184        
185        boolean showDays = durationCopy > 0;
186        boolean showHours = showDays || h > 0;
187        boolean showMinuts = showHours || m > 0;
188        boolean showSeconds = showMinuts || s > 0;
189
190        if (showDays)
191        {
192            sb.append(durationCopy);
193            sb.append("j ");
194        }
195        if (showHours)
196        {
197            sb.append(formatNumber(h, 2));
198            sb.append("h ");
199        }
200        if (showMinuts)
201        {
202            sb.append(formatNumber(m, 2));
203            sb.append("m ");
204        }
205        if (showSeconds)
206        {
207            sb.append(formatNumber(s, 2));
208            sb.append("s ");
209        }
210        sb.append(formatNumber(ms, 3));
211        sb.append("ms");
212        return sb.toString();
213    }
214    private static String formatNumber(long number, int nbNumbers)
215    {
216        String numberFormatted = String.valueOf(number);
217        while (numberFormatted.length() < nbNumbers)
218        {
219            numberFormatted = "0" + numberFormatted;
220        }
221        return numberFormatted;
222    }
223}