Given today's time e.g. 2:24PM, how do I get it to round to 2:30PM?
Similarly if the time was 2:17PM, how do I get it to round to 2:15PM?
Rounding
You will need to use modulo to truncate the quarter hour:
Date whateverDateYouWant = new Date();
Calendar calendar = Calendar.getInstance();
calendar.setTime(whateverDateYouWant);
int unroundedMinutes = calendar.get(Calendar.MINUTE);
int mod = unroundedMinutes % 15;
calendar.add(Calendar.MINUTE, mod < 8 ? -mod : (15-mod));
As pointed out by EJP, this is also OK (replacement for the last line, only valid if the calendar is lenient):
calendar.set(Calendar.MINUTE, unroundedMinutes + mod);
Improvements
If you want to be exact, you will also have to truncate the smaller fields:
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
You can also use DateUtils.truncate() from Apache Commons / Lang to do this:
calendar = DateUtils.truncate(calendar, Calendar.MINUTE);
If you just want to round down this is a more readable version using Java Time API:
LocalDateTime time = LocalDateTime.now();
LocalDateTime lastQuarter = time.truncatedTo(ChronoUnit.HOURS)
.plusMinutes(15 * (time.getMinute() / 15));
output:
2016-11-04T10:58:10.228
2016-11-04T10:45:00
A commented implementation for Java 8. Accepts arbitrary rounding units and increments:
public static ZonedDateTime round(ZonedDateTime input, TemporalField roundTo, int roundIncrement) {
/* Extract the field being rounded. */
int field = input.get(roundTo);
/* Distance from previous floor. */
int r = field % roundIncrement;
/* Find floor and ceiling. Truncate values to base unit of field. */
ZonedDateTime ceiling =
input.plus(roundIncrement - r, roundTo.getBaseUnit())
.truncatedTo(roundTo.getBaseUnit());
ZonedDateTime floor =
input.plus(-r, roundTo.getBaseUnit())
.truncatedTo(roundTo.getBaseUnit());
/*
* Do a half-up rounding.
*
* If (input - floor) < (ceiling - input)
* (i.e. floor is closer to input than ceiling)
* then return floor, otherwise return ceiling.
*/
return Duration.between(floor, input).compareTo(Duration.between(input, ceiling)) < 0 ? floor : ceiling;
}
Source: myself
It's simple, find the number of quaters since 1970 as double, round it and multiply by 15 minutes:
long timeMs = System.System.currentTimeMillis();
long roundedtimeMs = Math.round( (double)( (double)timeMs/(double)(15*60*1000) ) ) * (15*60*1000) );
Set your Date or Calendar object with that.
With the answer above you end up with all kind of interesting code to handle overflows to hours, days etc.
I would use the time in ms since the epoch.
add 7.5minutes or 7.5x60x1000 = 450000
and truncate to a multiple of 900000
new Date(900000 * ((date.getTime() + 450000) / 900000))
This works, because the time where the ms time starts happens to be 00:00:00. And since all time zones in the world change in 15min steps, this does not affect rounding to quarters.
(Oops, I had a 0 too much and forgot some important parentheses : it is still too early)
Wonderful post, thank you so much guys! It was exactly what I needed :)
Here's my code based on jour work.
My usecase is "Given it's 11:47 am, I want to set two dates symbolizing the current 5-minutes frame : 11:45 am and 11:50 am"
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
int modulo = calendar.get(Calendar.MINUTE) % 5;
if(modulo > 0) {
calendar.add(Calendar.MINUTE, -modulo);
}
myObject.setStartDate(calendar.getTime());
calendar.add(Calendar.MINUTE, 5);
myObject.setDueDate(calendar.getTime());
You can use this simple code...
int mode = min % 15;
if (mode > 15 / 2) {
min = 15 - mode;
} else {
min = 0 - mode;
}
cal.add(Calendar.MINUTE, min);
One more alternate approach using java Instant api.
Instant instant = Instant.now();
int intervalInMinutes = 10;
instant.truncatedTo(ChronoUnit.MINUTES).minus(instant.atZone(ZoneId.of("UTC")).getMinute() % (1* intervalInMinutes),ChronoUnit.MINUTES);
If you need to round down time to the nearest arbitrary level provided as Duration:
static long truncateTo(long timeEpochMillis, Duration d) {
long x = timeEpochMillis / d.toMillis();
return x * d.toMillis();
}
java.time
I recommend you do it using the the modern date-time API*:
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
// Change it to the applicable ZoneId e.g. ZoneId.of("Asia/Kolkata")
ZoneId zoneId = ZoneId.systemDefault();
Stream.of(
"10:00",
"10:05",
"10:10",
"10:15",
"10:20",
"10:25",
"10:30"
).forEach(t -> System.out.println(roundToNearestQuarter(t, zoneId)));
}
static ZonedDateTime roundToNearestQuarter(String strTime, ZoneId zoneId) {
LocalTime time = LocalTime.parse(strTime);
return LocalDate.now()
.atTime(time)
.atZone(zoneId)
.truncatedTo(ChronoUnit.HOURS)
.plusMinutes(15 * Math.round(time.getMinute() / 15.0));
}
}
Output:
2021-04-02T10:00+01:00[Europe/London]
2021-04-02T10:00+01:00[Europe/London]
2021-04-02T10:15+01:00[Europe/London]
2021-04-02T10:15+01:00[Europe/London]
2021-04-02T10:15+01:00[Europe/London]
2021-04-02T10:30+01:00[Europe/London]
2021-04-02T10:30+01:00[Europe/London]
In case you are looking for just time, use ZonedDateTime#toLocalTime to get the LocalTime from the obtained ZonedDateTime.
Learn more about the modern date-time API from Trail: Date Time.
* The java.util date-time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern date-time API. For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.
Maybe you can use an utility library for manipulating Dates, here for example you have a round method which can be useful for you:
http://commons.apache.org/lang/api-2.4/org/apache/commons/lang/time/DateUtils.html#round%28java.util.Calendar,%20int%29
Here an example in code:
FastDateFormat formatter = DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT;
Date now = new Date();
System.out.println("now = " + formatter.format(now));
// Get nearest second
Date nearestSecond = DateUtils.round(now, Calendar.SECOND);
System.out.println("nearestSecond = " + formatter.format(nearestSecond));
// Get nearest minute
Date nearestMinute = DateUtils.round(now, Calendar.MINUTE);
System.out.println("nearestMinute = " + formatter.format(nearestMinute));
// Get nearest hour
Date nearestHour = DateUtils.round(now, Calendar.HOUR);
System.out.println("nearestHour = " + formatter.format(nearestHour));
public static Date getCurrentDateTimeWithQuarterRounding() {
final Calendar calendar = new GregorianCalendar();
calendar.setTime(new Date());
calendar.set(Calendar.MILLISECOND, 0);
calendar.set(Calendar.SECOND, 0);
final int minutes = calendar.get(Calendar.MINUTE);
if (minutes < 15) {
calendar.set(Calendar.MINUTE, 0);
} else if (minutes >= 45) {
calendar.set(Calendar.MINUTE, 45);
} else if (minutes < 30) {
calendar.set(Calendar.MINUTE, 15);
} else {
calendar.set(Calendar.MINUTE, 30);
}
return calendar.getTime();
}
if you have the minutes you can round them with the following function:
int minutes = i % 15 < 8 ? i / 15 * 15 : (i / 15 + 1) * 15;
minutes = (int) (Math.round(minutes / 15.0) * 15.0);
Using some code on I found on Stackoverflow, I have created the following code. It will output for every minute the quarter it will be rounded to.
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
DateTimeFormatter Datum_Format = DateTimeFormatter.ofPattern("HH:mm");
LocalDateTime time = LocalDateTime.now();
for(int i=0; i<=59; i++) {
time = time.withMinute(i);
int Minute = time.getMinute();
int Quarter = 15 * (int) Math.round(Minute / 15);
if (Quarter == 60) {
Time2 = time.plusHours(1);
Time2 = Time2.withMinute(0);
LOG.info (Datum_Format.format(time) + "," + Datum_Format.format(Time2));
}
else {
Time2 = time;
Time2 = Time2.withMinute(Quarter);
LOG.info (Datum_Format.format(time) + "," + Datum_Format.format(Time2));
}
}
As I output the code to a console, you will have to replace the LOG.info with something like System.out.println.
Result:
2016-08-16 15:14:31 INFO 15:05,15:00
2016-08-16 15:14:31 INFO 15:06,15:00
2016-08-16 15:14:31 INFO 15:07,15:00
2016-08-16 15:14:31 INFO 15:08,15:15
2016-08-16 15:14:31 INFO 15:09,15:15
2016-08-16 15:14:31 INFO 15:10,15:15
Use the following functions to get the minutes rounded to last quarter getRecentQuater():Date, getSysDate_LastQuarterMins("dd.MM.yyyy HH:mm:ss"):String: Converting LocalDateTime to Date
public static Date getRecentQuater() {
LocalDateTime time = LocalDateTime.now();
LocalDateTime lastQuarter = time.truncatedTo(ChronoUnit.HOURS).plusMinutes(getLastQuarterValue(time.getMinute()));
System.out.println("lastQuarter LocalDateTime: " + lastQuarter);
Date date = Date.from(lastQuarter.atZone(ZoneId.systemDefault()).toInstant());
System.out.println("lastQuarter Date: " + lastQuarter);
return date;
}
public static String getSysDate_LastQuarterMins(String dateFormat) {
Date date = getRecentQuater();
SimpleDateFormat ft = new SimpleDateFormat (dateFormat);
String sysDate_RoundMin = ft.format(date);
System.out.println("getSysDate_LastQuarterMins() LocalDateTime : "+sysDate_RoundMin);
return sysDate_RoundMin;
}
getSysDate_LastQuarterMins() : Mon Jan 20 17:30:00 CET 2020
public static Date getSysDate_LastQuarterMins() {
Calendar cal = Calendar.getInstance();
cal.setTime( new Date(System.currentTimeMillis()) );
int min = cal.get(Calendar.MINUTE);
cal.set(Calendar.MINUTE, getLastQuarterValue(min));
cal.set(Calendar.SECOND, 00);
Date lastQuarter = cal.getTime();
System.out.println("getSysDate_LastQuarterMins() Calendar : "+lastQuarter);
return lastQuarter;
}
You can find the LastQuarter Value Round value from the follwing fucntions, provided with some outputs on function call diaplayLastQuarter_RoundValue(min):
Min: 10, LastQuarter: 0, Round: 15
Min: 24, LastQuarter: 15, Round: 30
Min: 36, LastQuarter: 30, Round: 30
Min: 37, LastQuarter: 30, Round: 30
Min: 38, LastQuarter: 30, Round: 45
Min: 39, LastQuarter: 30, Round: 45
Min: 44, LastQuarter: 30, Round: 45
Min: 57, LastQuarter: 45, Round: 00 [57, 07:45:00, 08:00:00]
public static void diaplayLastQuarter_RoundValue(int minutes) {
System.out.format("Min: %2d, LastQuarter: %2d, Round: %2d\n",
minutes, getLastQuarterValue(minutes), getRoundValue(minutes));
}
public static int getLastQuarterValue(int minutes) {
int min = 15 * (minutes / 15);
//System.out.println("Min: "+minutes+", getLastQuarterValue : "+ min);
return min;
}
public static int getRoundValue(int minutes) {
getLastQuarterValue(minutes);
int minRound = (int) (Math.round(minutes / 15.0) * 15.0);
//System.out.println("Min: "+minutes+", getRoundValue : "+minRound);
return minRound;
}
If someone is interested to get the nearest (up or down) five or fifteen interval, I made a function using module that does the job.
public LocalTime roundToTheNearestInterval(LocalTime original, Integer measurementInterval) {
LocalTime nearest;
int mod;
switch (measurementInterval) {
case 5:
mod = original.getMinute() % 5;
nearest = mod >= 3 ?
original.truncatedTo(ChronoUnit.HOURS)
.plusMinutes((long) 5 * (original.getMinute() / 5) + 5) :
original.truncatedTo(ChronoUnit.HOURS)
.plusMinutes((long) 5 * (original.getMinute() / 5));
break;
case 15:
mod = original.getMinute() % 15;
nearest = mod >= 8 ?
original.truncatedTo(ChronoUnit.HOURS)
.plusMinutes((long) 15 * (original.getMinute() / 15) + 15) :
original.truncatedTo(ChronoUnit.HOURS)
.plusMinutes((long) 15 * (original.getMinute() / 15));
break;
default:
nearest = original;
}
return nearest;
}
You can try it with this unit test
#Test
void roundToTheNearestInterval() {
//given
LocalTime originalTime1 = LocalTime.of(6, 31, 15);
LocalTime originalTime2 = LocalTime.of(19, 13, 42);
LocalTime originalTime3 = LocalTime.of(6, 37, 11);
LocalTime originalTime4 = LocalTime.of(19, 40, 34);
Integer measurementInterval_5min = 5;
Integer measurementInterval_15min = 15;
MyService myService = new MyService();
//when
LocalTime rounded1_5min = myService.roundToTheNearestInterval(originalTime1, measurementInterval_5min);
LocalTime rounded2_5min = myService.roundToTheNearestInterval(originalTime2, measurementInterval_5min);
LocalTime rounded1_15min = myService.roundToTheNearestInterval(originalTime3, measurementInterval_15min);
LocalTime rounded2_15min = myService.roundToTheNearestInterval(originalTime4, measurementInterval_15min);
//then
assertEquals(LocalTime.of(6, 30, 0), rounded1_5min);
assertEquals(LocalTime.of(19, 15, 0), rounded2_5min);
assertEquals(LocalTime.of(6, 30, 0), rounded1_15min);
assertEquals(LocalTime.of(19, 45, 0), rounded2_15min);
}
Related
IMPORTANT: external libraries, Date and Instant class are not allowed
You may not use any library routines for manipulation of time or
dates, such as converting UNIX time to a date string or for formatting
date strings in general. All calculations for determining year, month,
day, and time must appear in your source.
I wrote this program to convert from UNIX time (time in seconds since 12:00 AM January 1, 1970) to normal date and time. At first glance it seems to work fine, but in some tests it was off by exactly one day. The hours, minutes, months, and years are always correct, but the days are one too few.
For example, when using UNIX time 1234567890 the program produces 11:31 PM 02/13/2009, which is correct! However when inputing 1111111111 (10 1's), the program produces 1:58 AM 03/17/2005, where it should output 01:58 AM 03/18/2005. 64075132196 produces 7:49 AM 06/17/4000 (correct) but 95632040996 produces 7:49 AM 06/16/5000, where it should be the 17th day instead of the 16th.
In order to check my program, I entered a date and time into https://www.unixtimestamp.com/ and entered the resulting UNIX time into my program. (This is how I managed to get exact UNIX codes in the troubleshooting above).
I would appreciate help finding this error and additionally implementing a more efficient solution to this problem altogether.
import java.util.*;
class Main {
public static void main(String[] args) {
System.out.println("\nEnter UNIX time");
Scanner scan = new Scanner(System.in);
int[] monthDays = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int[] leapYearMonthDays = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
long unix = scan.nextLong();
int years = 0, months = 0, days = 0, hours = 0, minutes = 0;
boolean leapYear = false;
String AMPM = "AM";
while (unix >= 60) {
unix -= 60;
minutes++;
if (minutes >= 60) {
minutes -= 60;
hours++;
}
if (hours >= 24) {
hours -= 24;
days++;
}
if (leapYear) {
if (days >= leapYearMonthDays[months]) {
days -= leapYearMonthDays[months];
months++;
}
}
else {
if (days >= monthDays[months]) {
days -= monthDays[months];
months++;
}
}
if (months >= 12) {
if (isLeapYear(1970 + years)) leapYear = true; else leapYear = false;
months -= 12;
years++;
}
}
if (hours > 12) {
AMPM = "PM";
hours -= 12;
}
if (days == 0) days = 1;
String daysString = String.valueOf(days);
if (daysString.length() == 1) daysString = "0" + daysString;
String monthsString = String.valueOf(months + 1);
if (monthsString.length() == 1) monthsString = "0" + monthsString;
String minutesString = String.valueOf(minutes);
if (minutesString.length() == 1) minutesString = "0" + minutesString;
if (hours == 0) hours = 12;
System.out.println("\n" + hours + ":" + minutesString + " " + AMPM + " " + monthsString + "/" + daysString + "/" + (years + 1970));
}
public static boolean isLeapYear (int year) {
if (year % 4 == 0) {
if (year % 100 == 0) {
if (year % 400 == 0) {
return true;
}
else return false;
}
else return true;
}
return false;
}
}
You created your own code. That probably was the intent of the homework.
Now pinpoint the problem.
For that you can actually create a loop generating different Unix time values.
For each of these values calculate the date using your code, in parallel calculate the date using java.util.Date or java.util.Instant. Compare the dates and print results suitable so you can pinpoint the situations where your code produces deviations. Try to understand the deviations and improve your code.
With that you would not only exercise coding date calculations but also automated testing or test driven development.
Given
UNIX time (time in seconds since 12:00 AM January 1, 1970)
Assume if we convert 0 as integer timestmap in unix-epoch format to a java.util.Date we solved it.
Using java.util.Date (prior to Java 8)
long unixTimeInMilliseconds = 0;
Date convertedDate = new java.util.Date(unixTimeInMilliseconds);
System.out.println(convertedDate);
Prints:
Thu Jan 01 00:00:00 GMT 1970
Using java.time.Instant or suitable Java 8 class
You can also use the Java Date/Time API introduced since Java 8 in a similar manner:
long unixTimeInMilliseconds = 0; // 0 ms
Instant timestamp = Instant.ofEpochMilli(unixTimeInMilliseconds);
System.out.println(timestamp);
Prints:
1970-01-01T00:00:00Z
See also
Unix epoch time to Java Date object
I am creating a workday calendar which calculates which date the workday ends.
I have a code that sets daily worktime from e.g 8:00-16:00 (workDayStartStop).
And a code when given a start date and increment in days should print out which date .
Increment in workingdays could be e.g 1.5f (which means 8 + 4 hours working day) or 1.25f (8 + 2 working hours).
##Issues:
My code only prints the days and hours correctly, but it needs to calculate minutes too.
My code needs to calculate backwards too if negative values are provided in days to increment.
public void setWorkdayStartAndStop(Calendar start,
Calendar stop) {
ZonedDateTime startZdt = ((GregorianCalendar)
start).toZonedDateTime();
ZonedDateTime endZdt = ((GregorianCalendar)
stop).toZonedDateTime();
long wholeDays = ChronoUnit.DAYS.between(startZdt, endZdt);
startZdt = startZdt.plusDays(wholeDays);
Duration workDay = Duration.between(startZdt, endZdt);
this.workdayStartAndStop = (float) workDay.toMinutes() /
(float) Duration.ofHours(1).toMinutes();
}
public LocalDateTime getWorkdayIncrement(LocalDateTime
startDate, float incrementInWorkdays) {
Holidays holidays = new Holidays();
CalendarController cc = new CalendarController();
holidays.setHolidayIfIsSetToRecurring();
int days = (int) Math.abs(incrementInWorkdays);
float remaining = incrementInWorkdays - days;
float fHours = remaining * 24f;
int hours = (int) fHours;
remaining = fHours - hours;
float fMinutes = remaining * 60f;
int minutes = (int) fMinutes;
LocalDateTime mDateTime = null;
for (int i = 0; i <= days; i++) {
mDateTime =
startDate.plusDays(i).plusHours(hours).plusMinutes(minutes);
LocalDate toLocalDate = mDateTime.toLocalDate();
//if the incremented day is a holiday, skip to nextday
if (cc.isHoliday(toLocalDate)) {
days += 1;
}
}
return mDateTime;
}
}
public static void main(String[] args) {
WorkdayCalendar workdayCalendar = new WorkdayCalendar();
workdayCalendar.setWorkdayStartAndStop(
LocalDateTime.of(2020, 1, 1, 8, 0),
LocalDateTime.of(2020, 1, 1, 16, 0));
workdayCalendar.setRecurringHoliday(
MonthDay.of(5, 17));
workdayCalendar.setHoliday(LocalDate.of(2020, 5, 27));
LocalDateTime start = LocalDateTime.of(2020, 5, 24, 8, 5);
String datePattern = "dd-MM-yyyy HH:mm";
DateTimeFormatter europeanDateFormatter =
DateTimeFormatter.ofPattern(datePattern);
float increment = 1.5f;
System.out.println(
europeanDateFormatter.format(start) +
" with the addition of " +
increment +
" working days is " +
europeanDateFormatter.format(workdayCalendar.getWorkdayIncrement(start, increment)));
}
Output is:
24-05-2020 08:05 with the addition of 1.5 working days is 26-05-2020 20:05
starting 24th 8 o'clock in the morning it should end 25th 12 o'clock in the morning (8h + 4h) . 1 workday is only from 8-16, then it should skip to next day. it should only give results between 8-16 if startDate is set fra 08:00 and wokringhours is set to 8hours a day.
You are using outdated and broken date/time API which are confusing and error-prone. Use modern date/time API which are smart and intuitive:
import java.time.LocalDateTime;
import java.time.Month;
public class Main {
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.of(2020, Month.JUNE, 18, 21, 50, 5);
System.out.println(ldt);
// After 2.75 days
System.out.println(getWorkdayIncrement(ldt, 2.75f));
}
public static LocalDateTime getWorkdayIncrement(LocalDateTime startDate, float incrementInWorkdays) {
int days = (int) incrementInWorkdays;
float remaining = incrementInWorkdays - days;
float fhours = remaining * 24f;
int hours = (int) fhours;
remaining = fhours - hours;
float fminutes = remaining * 60f;
int minutes = (int) fminutes;
return startDate.plusDays(days).plusHours(hours).plusMinutes(minutes);
}
}
Output:
2020-06-18T21:50:05
2020-06-21T15:50:05
[Update]
Given below is how you can get LocalDate out of MonthDay:
import java.time.LocalDate;
import java.time.Month;
import java.time.MonthDay;
public class Main {
public static void main(String[] args) {
// Month-day of June, 20
MonthDay monthDay = MonthDay.of(Month.JUNE, 20);
LocalDate date = monthDay.atYear(2020);
System.out.println(date);
// Month-day now
monthDay = MonthDay.now();
date = monthDay.atYear(2020);
System.out.println(date);
}
}
Output:
2020-06-20
2020-06-20
I need to get time difference in my program.
ex: if user inserts earlier time as 08:30 and later time as 5:00 I need to calculate the time gap as 8 hours and 30 minutes(I want it to display as 08 hours 30 min)
I'm using phpmyadmin and my db has employee table,and in it there are three columns as earlierTime,laterTime and noOfHoursWorked and all these columns' data types are varchar(50) so i did this but output is not correct
public String timeDifference(String earlierTime, String laterTime) {
SimpleDateFormat format = new SimpleDateFormat("HH:mm");
Date date1 = format.parse(startTime);
Date date2 = format.parse(leavedTime);
long difference = date2.getTime() - date1.getTime();
String d = String.valueOf(difference);
return d;
}
can anyone please tell me what is wrong here I'm struggling with this problem for hours now
Is it okay if i change earlierTime, laterTime as date and noOfHoursWorked as int then i know in my output i can't get "8 hours 30 minutes" as output,so that I'd like to see it as "08:30"
java.time
In Java 8 and later use the java.time package. (Tutorial)
// Some exemplary dates
Calendar cal = Calendar.getInstance();
cal.set(2015, 9, 9, 10, 15, 0);
Date date1 = cal.getTime();
cal.set(2015, 9, 9, 14, 0, 20);
Date date2 = cal.getTime();
Duration duration = Duration.between(date1.toInstant(), date2.toInstant());
System.out.println(duration.toMinutes());
long minutes = duration.toMinutes()%60;
long hours = duration.toMinutes() / 60;
System.out.println("Duration " + hours + ":" + minutes);
long minutes = duration.toMinutes()%60;
long hours = duration.toMinutes() / 60; // this takes the math floor be default
System.out.println("Duration " + hours + ":" + minutes);
Joda-Time
In older Java, if only you can easily add external libraries, use Joda-Time. It's the best solution, since many peoples' workarounds do not take leap years into account while calculating date differences.
take a look at this :
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateDifferentExample {
public static void main(String[] args) {
String dateStart = "01/14/2012 09:29:58";
String dateStop = "01/15/2012 10:31:48";
//HH converts hour in 24 hours format (0-23), day calculation
SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
Date d1 = null;
Date d2 = null;
try {
d1 = format.parse(dateStart);
d2 = format.parse(dateStop);
//in milliseconds
long diff = d2.getTime() - d1.getTime();
long diffSeconds = diff / 1000 % 60;
long diffMinutes = diff / (60 * 1000) % 60;
long diffHours = diff / (60 * 60 * 1000) % 24;
long diffDays = diff / (24 * 60 * 60 * 1000);
System.out.print(diffDays + " days, ");
System.out.print(diffHours + " hours, ");
System.out.print(diffMinutes + " minutes, ");
System.out.print(diffSeconds + " seconds.");
} catch (Exception e) {
e.printStackTrace();
}
}
}
Friends,
I am looking to calculate the difference in days.
Hey suppose if I enter 31st Aug 23:59:00 and next date 1 Sept 00:02:00 , I need to show the record as 1 day.
Please help me for this one.
Right now I am calculating the same using .getTimeInMillis() but it is not giving me expected results for the date condition mentioned above.
I you look for day and time difference then, use my code
public class AndroidWebImage extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Date sdate=Calendar.getInstance().getTime();
SimpleDateFormat format = new SimpleDateFormat("dd/MM/yy HH:mm:ss");
String setDate = "13/09/12 10:20:43";
Date AlarmDate=new Date(setDate);
String currentDate = format.format(sdate);
Date d1 = null;
Date d2 = null;
try {
d1 = format.parse(setDate);
d2 = format.parse(currentDate);
} catch (ParseException e) {
e.printStackTrace();
}
//Comparison
long diff = d1.getTime() - d2.getTime();
long diffSeconds = diff / 1000 % 60;
long days = (int) (diff / (1000 * 60 * 60 * 24));
long diffHours = (int) ((diff- (1000 * 60 * 60 * 24 * days)) / (1000 * 60 * 60));
long diffMinutes = (int) (diff- (1000 * 60 * 60 * 24 * days) - (1000 * 60 * 60 * diffHours))/ (1000 * 60);
int curhour=sdate.getHours();
int curmin=sdate.getMinutes();
int alarmhour=AlarmDate.getHours();
int alarmmin=AlarmDate.getMinutes();
if(curhour==alarmhour && curmin==alarmmin)
{
Toast.makeText(getApplicationContext(), String.valueOf(days+"days\n"+diffHours+"hrs"+diffMinutes+"min\n"+diffSeconds+"sec"),Toast.LENGTH_LONG).show();
}
else if(curhour>=alarmhour && curmin>=alarmmin || curhour<=alarmhour && curmin<=alarmmin)
{
Toast.makeText(getApplicationContext(), String.valueOf(days+"days\n"+diffHours+"hrs"+diffMinutes+"min\n"+diffSeconds+"sec"),Toast.LENGTH_LONG).show();
}
}
}
You can't do this with millis, because you need to know where the day boundary falls (i.e. midnight). A millisecond either side of midnight means two different days.
You need to use a Calendar to determine how many days lie within the interval between your two dates. The JodaTime library has a lot of additional support for this kind of calculation.
See also Calculating the difference between two Java date instances
Your're just trying to find the number of days, right?
Try looking at this, it might have what you are looking for.
i made this code before, its may helps you
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
*
* #author MErsan
*/
public class DateFormatter {
public static String formatDate(long time) {
StringBuilder result = new StringBuilder();
// 1- Check the year
// 2- Check the Month
// 3- Check the Day
// 4- Check the Hours
Date myDate = new Date(time);
Date todayDate = new Date(System.currentTimeMillis());
if (todayDate.getYear() - myDate.getYear() != 0) {
// Not same year, and should append the whole time
return DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT).format(myDate);
}
// Same Year
// now Check the month
if (todayDate.getMonth() - myDate.getMonth() != 0) {
return new SimpleDateFormat("MMM dd, hh:mm a").format(myDate);// Aug
// 16,
// 11:55
// PM
}
// Now Same Month
// Check the day
int daysDiff = todayDate.getDate() - myDate.getDate();
if (daysDiff == 1) {// Yesterday
result.append("Yesterday").append(' ');
result.append(new SimpleDateFormat("hh:mm a").format(myDate));
return result.toString();
} else if (daysDiff != 0) {
return new SimpleDateFormat("MMM dd, hh:mm a").format(myDate);// Aug
// 16,
// 11:55
// PM
}
// Same Day :')
// Check the hour
int hoursDiff = todayDate.getHours() - myDate.getHours();
if (hoursDiff < 0) {// Invalid Time
// :#
result.append("Today").append(' ');
result.append(new SimpleDateFormat("hh:mm a").format(myDate));
return result.toString();
} else if (hoursDiff > 3) {// Not Same Hour, Hour Diff more than 3 hours
result.append("Today").append(' ');
result.append(new SimpleDateFormat("hh:mm a").format(myDate));
return result.toString();
} else if (hoursDiff != 0) {// Hours Diff less than 3 hours, but not
// current hour
int mintuesDiff = todayDate.getMinutes() - myDate.getMinutes();
result.append("Before").append(' ');
result.append(hoursDiff).append(' ');
result.append("Hours").append(' ');
result.append("and").append(' ');
result.append(Math.abs(mintuesDiff)).append(' ');
result.append("Minutes");
System.err.println("Case 6");
return result.toString();
} else if (hoursDiff == 0) {// Same Hours
int mintuesDiff = todayDate.getMinutes() - myDate.getMinutes();
if (mintuesDiff < 1) {// Seconds Only {Same Minute}
int secondsDiff = todayDate.getSeconds() - myDate.getSeconds();
result.append("Before").append(' ');
result.append(Math.abs(secondsDiff)).append(' ');
result.append("Seconds");
return result.toString();
} else {
result.append("Before").append(' ');
result.append(Math.abs(mintuesDiff)).append(' ');
result.append("Minutes");
return result.toString();
}
}
// Default
return DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT).format(myDate);
}
}
import java.util.Calendar;
public class DateDifference
{
public static void main(String[] args)
{
Calendar calendar1 = Calendar.getInstance();
Calendar calendar2 = Calendar.getInstance();
calendar1.set(2012, 01, 10);
calendar2.set(2012, 07, 01);
long milliseconds1 = calendar1.getTimeInMillis();
long milliseconds2 = calendar2.getTimeInMillis();
long diffDays = diff / (24 * 60 * 60 * 1000);
System.out.println("Time in days: " + diffDays + " days.");
}
}
You need to get rid of the timestamps and then subtract dates to get the difference in dates or you can use Joda-time as below:
import java.util.Date;
import org.joda.time.DateTime;
import org.joda.time.Days;
Date past = new Date(112, 8, 1);
Date today = new Date(112, 7, 30);
int days = Days.daysBetween(new DateTime(past), new DateTime(today)).getDays();
Re-post:
There's a simple solution, that at least for me, is the only feasible solution.
The problem is that all the answers I see being tossed around - using Joda, or Calendar, or Date, or whatever - only take the amount of milliseconds into consideration. They end up counting the number of 24-hour cycles between two dates, rather than the actual number of days. So something from Jan 1st 11pm to Jan 2nd 1am will return 0 days.
To count the actual number of days between startDate and endDate, simply do:
// Find the sequential day from a date, essentially resetting time to start of the day
long startDay = startDate.getTime() / 1000 / 60 / 60 / 24;
long endDay = endDate.getTime() / 1000 / 60 / 60 / 24;
// Find the difference, duh
long daysBetween = endDay - startDay;
This will return "1" between Jan 2nd and Jan 1st. If you need to count the end day, just add 1 to daysBetween (I needed to do that in my code since I wanted to count the total number of days in the range).
/** Determines the difference in days between d and this Date.For example,
* if this Date is 12/15/1997 and d is 12/14/1997, the difference is 1.
* If this Date occurs before d, the result is negative.
* #return the difference in days between d and this date.
*/
public int difference(Date d) {
int NoOfLeapYr_d = d.year/4;
int NoOfLeapYr_this = this.year/4;
int daysofthis = NoOfLeapYr_this + (this.year-1 * 365) + this.dayInYear();
int daysofd = NoOfLeapYr_d + (d.year-1 * 365) + d.dayInYear();
return daysofd - daysofthis;
}
I have made this logic ...and it's not working. It's returning the wrong answer. Can anybody help in the logic?
Using Joda Datetime:-
#Test
public void testOneDayEarlier() {
DateTime fromDate = new DateTime(2011, 2, 12, 0, 0, 0, 0);
DateTime toDate = new DateTime(2011, 2, 13, 0, 0, 0, 0);
int days = Days.daysBetween(fromDate, toDate).getDays();
assertEquals("fromDate is one day earlier than toDate", 1, days);
}
#Test
public void testOneDayLater() {
DateTime fromDate = new DateTime(2011, 2, 13, 0, 0, 0, 0);
DateTime toDate = new DateTime(2011, 2, 12, 0, 0, 0, 0);
int days = Days.daysBetween(fromDate, toDate).getDays();
assertEquals("fromDate is one day later than toDate", -1, days);
}
#Test
public void testSameDay() {
DateTime fromDate = new DateTime(2011, 2, 13, 0, 0, 0, 0);
DateTime toDate = new DateTime(2011, 2, 13, 0, 0, 0, 0);
int days = Days.daysBetween(fromDate, toDate).getDays();
assertEquals("fromDate is the same as toDate", 0, days);
}
If you have two date objects, it's much simpler to subtract the millisecond times:
long diff = today.getTime() - d1.getTime();
And then convert the time difference to a day difference:
long days_diff = diff / (1000*60*60*24);
Note: this only works for dates since Jan 1, 1970
If you try to replicate all the calendar logic yourself (e.g. leap years), there's a good chance you'll get it wrong. There are a surprising number of subtle corner cases to bite you, and others have already figured it all out.
And if you need serious multi-calendar Java date handling, see JODA: http://joda-time.sourceforge.net/
Your logic to determine the number of leap years is incorrect. See the answer from Alok on this question:
How to find leap year programatically in C
If you are only going to be dealing with dates between the years 1900 and 2100, there is a simple calculation which will give you the number of days since 1900:
public static int daysSince1900(Date date) {
Calendar c = new GregorianCalendar();
c.setTime(date);
int year = c.get(Calendar.YEAR);
if (year < 1900 || year > 2099) {
throw new IllegalArgumentException("daysSince1900 - Date must be between 1900 and 2099");
}
year -= 1900;
int month = c.get(Calendar.MONTH) + 1;
int days = c.get(Calendar.DAY_OF_MONTH);
if (month < 3) {
month += 12;
year--;
}
int yearDays = (int) (year * 365.25);
int monthDays = (int) ((month + 1) * 30.61);
return (yearDays + monthDays + days - 63);
}
Thus, to get the difference in days between two dates, you calculate their days since 1900 and calc the difference. Our daysBetween method looks like this:
public static Integer getDaysBetween(Date date1, Date date2) {
if (date1 == null || date2 == null) {
return null;
}
int days1 = daysSince1900(date1);
int days2 = daysSince1900(date2);
if (days1 < days2) {
return days2 - days1;
} else {
return days1 - days2;
}
}
And don't ask me where this calculation came from because we've used it since the early '90s.