I found this funny behavior while using Date and Calendar class to handle Exponential distributions for simulating arrival time at a store (academic work). The code is quite simple and is below displayed. Well suppose that "this.currentDate" is "Feb 15 08:00:00 BRST 2014".
If i shift forward the time 24h (parameter iSeconds=86.400), what is supposed to return ? The expected string would be "2014-02-16 08:00:00" but instead the time is shortened in 1h and the result is "2014-02-16 07:00:00", I wonder if someone could explain why my one hour was "stolen". No big deal, but since my next arrival time depends of the earlier one, it makes a mess over my time baseline shifting all of them one hour as well.
I thought could be some TZ issue, but heck, i just moved 24h in the middle of February.
public String shiftTimeStamp( int iSeconds)
{
Calendar cal = Calendar.getInstance();
cal.setTime(this.currentDate);
cal.add(Calendar.SECOND, iSeconds);
this.currentDate = cal.getTime();
String sTS = new SimpleDateFormat(SCSimLabels.DATE_TS_FORMAT).format(this.currentDate);
return sTS;
}
Note: Daylight Saving Time issue :) BRT <--> BRST tz.
my workaround: I just want a beacon to guide the time jumps caused by inter arrival times and I´m not interested on such calendar specificities, so when I need to move to the first work hour of the next day I just force the time to be 08:00:00 after 1 day shift. It works like a charm :)
Calendar cal = Calendar.getInstance();
cal.setTime(this.currentDate);
cal.add(Calendar.DATE, 1);
String sDate = (new SimpleDateFormat("yyyy-MM-dd 08:00:00")).format(cal.getTime());
Date newDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(sDate);
this.currentDate = newDate;
Change the format call to this:
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z").format(this.currentDate);
To see what timezone the format call is using. I bet the call to .add() is modifying the Calendar object's timezone since it crosses the standard time / daylight time border.
If this is the case, you could try adding a Calendar.DAY,1 or simply .setTimeZone(...) of the Calendar obj. back to the original timezone after the .add call.
Avoid legacy date-time classes
You are using troublesome old date-time classes that are now legacy, supplanted by the java.time classes.
Using java.time
If you want to work with generic 24-hour days without any time zone or offset-from-UTC, use the LocalDateTime class. If you always want to start at 8 AM, specify a LocalTime.
LocalDate ld = LocalDate.of( 2014 , Month.FEBRUARY , 15 ) ;
LocalTime lt = LocalTime.of( 8 , 0 ) ; // Specify hour in 24-hour clock, 0-23.
LocalDateTime ldt = LocalDateTime.of( ld , lt );
Represent your 24 hour span as a Duration.
Duration d = Duration.ofHours( 24 );
LocalDateTime ldtLater = ldt.plus( d );
If you want to work with specific moments on the timeline as seen through the lens of a region’s particular wall-clock time, then specify a ZoneId to get a ZonedDateTime.
ZoneId z = ZoneId.of( "America/Sao_Paulo" ) ;
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;
ZonedDateTime zdtLater = zdt.plus( d );
Note that adding 24 hours to a ZonedDateTime is not the same thing as adding a day. As you have learned the hard way, anomalies such as Daylight Saving Time (DST) means a day may be 23, 24, or 25 hours long, or even other lengths. So if you want to add a day and let java.time apply its logic to arrive at an appropriate time-of-day while taking into consideration anomalies such as DST, add days rather than hours.
ZonedDateTime zdtLater = zdt.plusDays( 1 );
Or add a Period of one whole day rather than a Duration of 24 hours.
Period p = Period.ofDays( 1 );
ZonedDateTime zdtLater = zdt.plus( p );
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
Related
I am new to Java's Date class. When I try to use its getTime() function for calculating time difference, issues come out. For example, below is the code.
Date date = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
task = opt.get();
task.setEndDate(dateFormat.format(date));
Date startDate = null;
try {
startDate = dateFormat.parse(task.getStartDate());
} catch (ParseException e) {
System.out.println("date parsing error...");
startDate = date;
}
System.out.printf("Start date is: %s", task.getStartDate());
System.out.printf("Start date is: %d", startDate.getTime());
System.out.printf("End date is: %s", task.getEndDate());
System.out.printf("End date is: %d", date.getTime());
long diff = date.getTime() - startDate.getTime() - 43200000;
System.out.printf("Time difference is: %d", diff);
int secNum = (int)(diff / 1000);
String timeCost = String.valueOf(secNum);
System.out.println("Time cost(sec) is:");
System.out.println(timeCost);
task.setTimeCost(timeCost);
The outputs are:
Start date is: 2020-04-15 01:46:17
Start date is: 1586929577000
End date is: 2020-04-15 01:46:35
End date is: 1586972795461
Time difference is: 18461
Time cost(sec) is:18
As you might notice, there is 12 hours(43200000 ms) offset between the calculated difference and the real difference through "date.getTime() - startDate.getTime()".
I don't know what's going on.
Does anyone have an idea and correct me ?
It seems you are storing the date/time as a string in your task object, and converting between Date and String using the format "yyyy-MM-dd hh:mm:ss". I believe lower-case h means you are using a 12-hour clock, but you do not include an AM/PM indicator in your format string.
I'm guessing you ran the code at 1:46 PM to produce the sample output.
You have "2020-04-15 01:46:17" stored as your start date. When you convert that back to a date, the formatter doesn't know whether it is an AM time or PM time. I guess that it defaults to AM.
The Date object, however, knows that it was initialized with a PM time. Therefore, when you subtract the two, you get over 12 hours difference, because it is subtracting 1:46:17 AM from 1:46:35 PM.
A simple recommendation would be to add an AM/PM indicator to your date format, or use a 24-hour clock (upper-case H in the format string).
An even better recommendation would be to store dates as dates, not as strings! Convert them to strings when you want to display them.
You are using hh which is a 12-hour hour format, hence 20:00 becomes 08:00. You should use HH which is a 24-hour format. The below illustrates the difference.
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
Date date = new Date(1586973600000L);
System.out.println(date);
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String fd1 = df.format(date);
System.out.println(fd1);
System.out.println(df.parse(fd1));
df.applyPattern("yyyy-MM-dd HH:mm:ss");
String fd2 = df.format(date);
System.out.println(fd2);
System.out.println(df.parse(fd2));
Also, java.util.Date is old, buggy and generally avoided for some time now. You might want to switch to java.time instead.
java.time
I am new to Java's Date class.
Stop! Backup, rewind.
Both java.util.Date and java.sql.Date classes are terrible, deeply flawed, and quite frustrating. Never use these classes.
These classes were shipped in the earliest versions of Java. Supplanted years ago by the modern java.time classes defined in JSR 310.
Date date = new Date();
To capture the current moment in UTC, use Instant.now. Uses a resolution finer than the milliseconds used in the java.util.Date class it replaced.
Instant instant = Instant.now() ; // Capture the current moment in UTC.
task.setEndDate(dateFormat.format(date));
Your Task class should hold a java.time object rather than a mere string.
class Task {
Instant start , stop ;
…
}
Use smart objects rather than dumb strings throughout your Java codebase. Doing so ensures valid values, provides type-safety, and makes your code more self-documenting.
If your Task is like booking appointments in the future, where you want a certain time-of-day regardless of changes to the offset used by your time zone, then use LocalDateTime. This type represents only a date and time-of-day but lacks any concept of time zone or offset.
LocalDate ld = LocalDate.of( 2020 , Month.APRIL , 15 ) ;
Localtime lt = LocalTime.of( 15 , 30 ) ;
LocalDateTime ldt = LocalDateTime.of( ld , lt ) ;
When generating a calendar where you need a specific point on the timeline, then apply the relevant time zone.
ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;
The issue at stake here is the fact that politicians around the world have shown a predilection for changing the offset used by the time zone(s) of their jurisdiction. The politicians do so with surprising frequency. And they have done so with little or no forewarning.
When exchanging date-time values with other systems textually, then use ISO 8601 formats. These formats are used by default in java.time when parsing/generating text. And for presentation to users, produce automatically localized strings using DateTimeFormatter.
new SimpleDateFormat("yyyy-MM-dd hh:mm:ss")
This format is incorrect if you are trying to record moments, specific points on the timeline. You must include an indication of time zone and/or offset-from-UTC to track a moment.
For moments, use the ISO 8601 formats mentioned above. Used by default, so no need to specify a formatting pattern.
String input = "2020-01-23T01:23:45.123456789Z" ;
Instant instant = Instant.parse( input ) ;
Adjust from UTC into the wall-clock time used by the people of a particular region (a time zone).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
Generate localized text.
Locale locale = Locale.CANADA_FRENCH ;
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( locale ) ;
String output = zdt.format( f ) ;
See this code run live at IdeOne.com.
zdt.toString(): 2020-01-22T20:23:45.123456789-05:00[America/Montreal]
output: mercredi 22 janvier 2020 à 20 h 23 min 45 s heure normale de l’Est
long diff = date.getTime() - startDate.getTime() - 43200000;
No need to do the math yourself. We have a class for that: Duration.
Duration d = Duration.between( start , stop ) ;
If you want a count of whole seconds across the entire span of time, call Duration::toSeconds.
long seconds = d.toSeconds() ; // Entire duration in terms of whole seconds.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes. Hibernate 5 & JPA 2.2 support java.time.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
I have the following timestamp stored in a long variable: 1471906800000 this stores the date 18/01/2017 00:00:00
I'm trying to create another timestamp that will contain the same date as stored in the first timestamp, but with the time being 23:59:59 -
I don't even know where to start
How could I achieve this in the most simple way possible in Java?
Thanks.
Using Calendar will help you:
long l = 1471906800000l;
Date date = new Date(l);
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.HOUR, 23);
calendar.set(Calendar.MINUTE, 59);
calendar.set(Calendar.SECOND, 59);
l = calendar.calendar.getTimeInMillis();
Both of the other Answers use outmoded classes, now supplanted by the java.time classes.
Perhaps your input number is a count of milliseconds from the epoch of first moment of 1970 in UTC (1970-01-01T00:00:00Z). But I do not get the result you stated in the question.
long input = 1_471_906_800_000L ;
Instant instant = Instant.ofEpochMilli( input );
input: 1471906800000
instant: 2016-08-22T23:00:00Z
But you expected the value of 18/01/2017 00:00:00, off by a few months. If your input is not a count of milliseconds from 1970-01-01T00:00:00Z, you need to edit your Question to specify.
If you made a mistake in your expected output, then let's proceed to set the time-of-day.
If you wanted the second before the end of the day, I suggest subtracting a second from the start of the following day rather than hard-coding the time of 23:59:59. That time-of-day may be invalid because of anomalies such as Daylight Saving Time (DST). Also, unless you meant intend to work in UTC, you need to move into the desired/expected time zone.
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );
Extract a LocalDate, for a date-only value without time-of-day and without time zone.
LocalDate ld = zdt.toLocalDate();
Move to next day.
LocalDate ldNextDay = ld.plusDays( 1 );
Ask for first moment.
ZonedDateTime zdtNextDay = ldNextDay.atStartOfDay( z );
Subtract a second to move back into previous day.
ZonedDateTime zdtPreviousDay = zdtNextDay.minusSeconds( 1L );
However, I suspect you are taking the wrong approach to handling date-time values. Rather than trying to determine the end of a day, I strongly suggest you follow the common practice of using the Half-Open approach to spans of time. In Half-Open, the beginning is inclusive while the ending is exclusive.
So a full day starts with the first moment of one day and runs up to, but not including, the first moment of the next day. This way you avoid the problem of the last second or trying to get the infinitely divisible fraction of a second.
ZonedDateTime zdtDayStart = LocalDate.of( 2017 , Month.JANUARY , 18 ).atStartOfDay( 1 );
ZonedDateTime zdtDayStop = zdtDayStart.plusDays( 1 );
You may find the Interval class in the ThreeTen-Extra project helpful.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8 and SE 9 and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
I'm assuming that you don't specifically want the time at 23:59:59, but rather a time 1 minute before the start of the next day.
You should use a date/time library. I know jodatime better, so this example is written using that, but you may be able to use the Java 8 time API instead.
DateTime today = new DateTime(1471906800000L, TIME_ZONE);
// You may want to check that today is actually at the start of the day.
// e.g. today.equals(today.withTimeAtStartOfDay());
DateTime lastMinuteOfToday =
today.toLocalDate()
.plusDays(1)
.toDateTimeAtStartOfDay(TIME_ZONE)
.minusMinutes(1);
long lastMinuteOfTodayMillis = lastMinuteOfToday.getMillis();
Knowing the timezone is important to do this correctly.
how to compare three date/time values in java?
Currently i use Date objects
I mean:
Date1 - today, 10:00PM
Date2 - tomorrow, 5:00AM
Date3 - current time
Is date3 between date1 and date2, respect date AND time?
date1.compareTo(date3) * date2.compareTo(date3) > 0
and
date1.after(date3) && date2.before(date3)
are not working.
I use this code in Android App, and if i set my time to 11.30AM, it still returns true for above conditions. If i use Time-objects and 2nd method, it doesn't recognise my time span is between 2 days.
Any idea?
EDIT: To make it exact, here is my current code. app is something like an alarm clock.
// Current Date/Time
Date now = Calendar.getInstance().getTime();
// Time when user goes to bed (current day)
Date sleep = new Date(now.getYear(), now.getMonth(), now.getDate(), Shours, Sminutes);
// Time when user wakes up (next day)
// Get Next Day's Date and set Time
Calendar wk = Calendar.getInstance();
wk.setTime(sleep);
wk.set(Calendar.HOUR_OF_DAY, Whours);
wk.set(Calendar.MINUTE, Wminutes);
// tomorrow
wk.add(Calendar.DATE, 1);
// and convert to date
Date wake = wk.getTime();
// Compare
if(now.after(sleep) && now.before(wake)) {
Log.d("uSleep", "Debug: Night time");
}
else {
Log.d("uSleep", "Debug: Day Time");
}
Maybe it's still too hard to understand. Image you go to bed at 10PM and you get up at 5AM. Now how to find out if you're sleeping by comparing your "go to bed"-time and you "get up"-time to the current time. I need to use "tomorrow" for your "get up"-time, otherwise java seems to compare all times for the same day, which is impossible.
tl;dr
Interval.of(
start ,
stop
).contains(
ZonedDateTime.now( ZoneId.of( "America/Montreal" ) )
.toInstant()
)
Details
The question is confusing, but seems to be…
How do I tell if a particular moment occurs within a span of time?
java.time
I mean: Date1 - today, 10:00PM Date2 - tomorrow, 5:00AM Date3 - current time
A time zone is crucial in determining “today” and “tomorrow”. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime now = ZonedDateTime.now( z );
To get the same date with another time-of-day, extract LocalDate. The LocalDate class represents a date-only value without time-of-day and without time zone. Specify desired time-of-day with LocalTime. Combine with ZoneId to get a ZonedDateTime.
LocalDate today = now.toLocalDate() ;
LocalTime tenPm = LocalTime.of( 22 , 0 ) ; // 10 PM is 22:00.
ZonedDateTime tenPmToday = ZonedDateTime.of( today , tenPm , z ) ;
To get tomorrow, add one day to today's date.
LocalDate tomorrow = ld.plusDays( 1 ) ;
LocalTime fiveAm = LocalTime.of( 5 , 0 ) ;
ZonedDateTime fiveAmTomorrow = ZonedDateTime.of( tomorrow ,fiveAm , z ) ;
Compare
To compare, call the isBefore, isEqual, and isAfter methods.
Boolean contains = ( ! now.isBefore( tenPmToday ) ) && now.isBefore( fiveAmTomorrow ) ;
Of course, now will always be before tomorrow, so I'm not sure of your intentions here.
org.threeten.extra.Interval
You may find the Interval class useful for this work, from the ThreeTen-Extra project listed below. This class stores a pair of Instant objects, and has some handy comparison methods such as contains.
The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
Interval interval = Interval.of( tenPmToday.toInstant() , fiveAmTomorrow.toInstant() ) ;
Boolean contains = interval.contains( now.toInstant() ) ;
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
Joda-Time
Update: the Joda-Time project is now in maintenance mode, with the team advising migration to the java.time classes.
The best way is to use the Joda-Time library, rather than the java.util.Date/.Calendar classes which are notoriously troublesome, confusing, and flawed.
Span Of Time
In Joda-Time you can represent a span of time in three ways: Interval, Period, and Duration. In this case, we need Interval, defined by a pair of specific points in the timeline, with the half-open [) approach where the beginning is inclusive and the ending exclusive.
The pair of specific points, as well as the current moment now, are all represented by the DateTime class. Unlike a java.util.Date, a DateTime knows its own assigned time zone. If unspecified, the JVM’s current default time zone will be applied. So generally better to specify.
Example Code
Some example code using Joda-Time 2.5.
DateTimeZone zone = DateTimeZone.forID( "America/Montreal" );
DateTime now = DateTime.now( zone );
DateTime bedtime = now.withTime( 22, 0, 0, 0 ); // Today’s bedtime. May be past, future, or this very moment now.
DateTime risetime = bedtime.plusHours( 7 ); // 05:00 next morning.
Interval sleepInterval = new Interval( bedtime, risetime );
boolean asleep = sleepInterval.contains( now ); // Half-Open "[)" comparison, beginning is inclusive, ending exclusive.
My program takes the current date and then, in a loop, adds a week to that date and prints out the new date. Something like:
Calendar cal = Calendar.getInstance();
for (int i=0; i < 52; i++) {
cal.add(Calendar.DATE, 7);
// print date out
}
The add method works the way I expect it to until it reaches Dec 30, at which point the year jumps from 2012 to 2013.
so, using today's date of 4/16/2012, i tested a few different inputs:
this - cal.add(Calendar.DATE, 38*7);
yields- "date:1/7/2013"
this - cal.add(Calendar.DATE, 37*7);
yields- "date:12/31/2013"
this - cal.add(Calendar.DATE, 37*7-1);
yields- "date:12/30/2013"
this - cal.add(Calendar.DATE, 37*7-2);
yields- "date:12/29/2012"
so i notice that the year is correct up until dec 30 and dec 31, and then it corrects itself again when it gets back to january. is there a reason why it does this? does it have anything to do with 2012 being a leap year or am i misunderstanding the add method
Did you use SimpleDateFormat to print the date and use YYYY to produce the year? If so, that is where the problem lies. Because YYYY produces the week-year and not the calendar year. And as 30/12/2012 is in calendar week 1 of 2013, YYYY produces 2013. To get the calendar year, use yyyy in your SimpleDateFormat format string.
See https://bugs.openjdk.java.net/browse/JDK-8194625
tl;dr
Use modern java.time classes, never the terrible legacy classes such as Calendar.
LocalDate // Represent a date-only value with `LocalDate`, without time-of-day and without time zone.
.now( // Capture the current date.
ZoneId.systemDefault() // Specify your desired/expected time zone explicitly.
) // Returns a `LocalDate` object.
.plusWeeks( 1 ) // Add a week, producing a new `LocalDate` object with values based on the original, per the immutable objects pattern.
.toString() // Generate text representing this date value in standard ISO 8601 format of YYYY-MM-DD.
2019-01-23
java.time
The modern approach uses the java.time classes.
The Calendar and GregorianCalendar classes are terrible, badly designed with flaws. Avoid them. Now replaced specifically by the ZonedDateTime class.
LocalDate
The LocalDate class represents a date-only value without time-of-day and without time zone or offset-from-UTC.
A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment during runtime(!), so your results may vary. Better to specify your desired/expected time zone explicitly as an argument.
Specify a proper time zone name in the format of Continent/Region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
LocalDate today = LocalDate.now( z ) ;
To generate text representing that date value in standard ISO 8601 format, simply call toString.
String output = today.toString() ;
Date math is easy, with various plus… & minus… methods.
LocalDate weekLater = today.plusWeeks( 1 ) ;
You can also define a span of time as a Period or Duration. Then add that.
Period p = Period.ofWeeks( 1 ) ;
LocalDate weekLater = today.plus( p ) ;
Your example
Let's test out your example dates.
LocalDate ld = LocalDate.of( 2012 , Month.APRIL , 16 ) ;
Period period38Weeks = Period.ofWeeks( 38 ) ;
Period period37Weeks = Period.ofWeeks( 37 ) ;
Period period37WeeksLess1Days = period37Weeks.minusDays( 1 ) ;
Period period37WeeksLess2Days = period37Weeks.minusDays( 2 ) ;
LocalDate later_38 = ld.plus( period38Weeks ) ;
LocalDate later_37 = ld.plus( period37Weeks ) ;
LocalDate later_37_1 = ld.plus( period37WeeksLess1Days ) ;
LocalDate later_37_2 = ld.plus( period37WeeksLess2Days ) ;
Run code live at IdeOne.com. No problems. The 38th week is in 2013, while week 37 dates are in 2012.
later_38.toString(): 2013-01-07
later_37.toString(): 2012-12-31
later_37_1.toString(): 2012-12-30
later_37_2.toString(): 2012-12-29
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
It should be:
cal.add(Calendar.DAY_OF_YEAR, 7);
Calendar.DATE is same as Calendar.DAY_OF_MONTH.
Overview
This is the scenario: I'm given a value which represents a portion of the total number of minutes that exist in a standard week (assuming 10,080 minutes a week and 1,440 minutes a day) starting midnight Saturday (so 0 minutes Sunday # 12am).
I need to convert this minute value into an actual time value (like 8:35am) and I want to use Java's Date and/or Calendar classes rather than calculate this by hand.
Example
Below are some example input values:
720 (720 minutes into the week) so 12pm on Sunday
3840 (3840 minutes into the week) so 4pm on Tuesday
Using Java's Date and Calendar classes how do I retrieve time component for that relative day?
Also, with a Calendar is really easy:
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
int minutesToAdd = 720;
Calendar cal = Calendar.getInstance();
cal.setTime(dateFormat.parse("2009/06/21 00:00:00")); // Next sunday
cal.add(Calendar.MINUTE, minutesToAdd);
Date result = cal.getTime(); // Voila
Divide by 24 hours in a day to get number of days. Remainder is number of minutes into that day.
Divide by 60 to get hour. Remainder is minutes into that hour.
Division and Modulus will get your answer in just a few lines of code. Since this sounds like homework, I'll leave the coding out of this answer.
As it sounds like homework, here how it should work:
1) Create yourself a calendar instance for sunday, 0:00 (on any date you wish)
2) Now add your minutes with the appropiate function
3) Now retrieve the time parts from the object
tl;dr
LocalDate.now( ZoneId.of( "America/Montreal" ) )
.with( TemporalAdjusters.previousOrSame( DayOfWeek.SUNDAY ) )
.atStartOfDay( ZoneId.of( "America/Montreal" ) )
.plus( Duration.ofMinutes( 720 ) )
Using java.time
The modern way is with the java.time classes.
Which week? I will assume you want the Sunday of the current week.
ZoneId z = ZoneId.of( "America/Montreal" ) ;
LocalDate today = LocalDate.now( z );
LocalDate sundayThisWeek = today.with( TemporalAdjusters.previousOrSame( DayOfWeek.SUNDAY ) );
Get the first moment of that date. Do not assume that means 00:00:00 as anomalies such as Daylight Saving Time (DST) may mean another time like 01:00:00.
ZonedDateTime zdt = sundayThisWeek.atStartOfDay( z ); // First moment of the day.
You say you are given an input of a number of minutes. Represent that as a Duration object.
Duration duration = Duration.ofMinutes( x );
Add the Duration object to your ZonedDateTime object.
720 (720 minutes into the week) so 12pm on Sunday
No, 720 minutes may result in some other time-of-day, such as 11 AM or 1 PM in the United States on the DST cutover day.
The objects do all the math for you, and handle anomalies such as Daylight Saving Time.
ZonedDateTime zdtLater = zdt.plus( duration );
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8 and SE 9 and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.