tl;dr
LocalDateTime.parse(
"2015-08-18 00:00:00".replace( " " , "T" ) // Convert input string to comply with ISO 8601 standard format, replacing SPACE in the middle with a `T`.
).plus(
Duration.ofDays( 31 ) // If you meant ( 31 * 24-hours ).
// Period.ofDays( 31 ) // If you meant 31 calendar-days.
// Period.ofMonths( 1 ) // If you meant a calendar-month.
) // Returns a fresh `LocalDateTime` object, distinct from original, per Immutable Objects pattern.
.toString() // Generate a string in standard ISO 8601 format to textually represent this object’s value.
2015-09-18T00:00
Terms
The word “offset” here is a poor choice of terms. That word has a specific meaning in date-time handling: the amount of hours, minutes, and seconds a time zone is from UTC. See the Wikipedia entry for UTC offset.
You seem to be concerned instead with a span of time unattached to the timeline. In the java.time classes such spans are called a Duration
if in the scale of hours-minutes-seconds, and called Period
if scaled in years-months-days.
java.time
The modern approach uses the java.time classes that supplanted the troublesome old date-time classes such as Date
/Calendar
.
Duration
Convert your span of time from a count of milliseconds to a Duration
object.
Duration d = Duration.ofMillis( 2_678_400_000L );
This happens to be 744 hours.
d.toString(): PT744H
Out of curiosity, I checked the number of days in 744 hours, if we define “days” to be chunks of 24-hours.
d.toDaysPart(): 31
So it seems you really intend a month or a period of 31 days. Either way, Java has classes for that.
If you really want: ( 31 * 24 hours ), then do use a Duration
. But construct the Duration
object with more self-documenting code.
Duration d = Duration.ofDays( 31 ) ; // Exact same effect as `Duration.ofMillis( 2_678_400_000L )` but more clear as to your intention.
ISO 8601
Your input string almost complies with ISO 8601 standard for date-time formats. The java.time classes use the standard formats by default when parsing/generating strings.
Convert your string to comply. Replace the SPACE in the middle with a T
.
String input = "2015-08-18 00:00:00".replace( " " , "T" ) ;
2015-08-18T00:00:00
LocalDateTime
Parse your input as a LocalDateTime
as your input lacks an indicator of offset-from-UTC or time zone.
LocalDateTime ldt = LocalDateTime.parse( input ) ;
ldt.toString(): 2015-08-18T00:00
Add your Duration
object to get a new fresh LocalDateTime
. The java.time classes use immutable objects so the original object is left intact.
LocalDateTime thirtyOneTimes24HoursLaterLdt = ldt.plus( d ) ; // Adding a span-of-time to our `LocalDateTime` object to get another `LocalDateTime` object.
thirtyOneTimes24HoursLaterLdt.toString(): 2015-09-18T00:00
Be aware that LocalDateTime
does not represent an actual moment, a specific point on the timeline. Without the context of a time zone or offset-from-UTC, it is only a rough idea about potential moments along a range of about 26-27 hours.
ZonedDateTime
If you know for certain your input string was meant to represent a moment in a particular zone, apply a ZoneId
to get a ZonedDateTime
object (an actual moment).
ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ; // Now we have determined an actual moment, a point on the timeline.
zdt.toString(): 2015-08-18T00:00+12:00[Pacific/Auckland]
You can add your Duration
if you do not care about dates (whole days on the calendar).
ZonedDateTime thirtyOneTimes24HoursLaterZdt = zdt.plus( d ) ;
thirtyOneTimes24HoursLaterZdt.toString(): 2015-09-18T00:00+12:00[Pacific/Auckland]
If your business logic was really meant to be thirty-one days on the calendar, use a Period
.
ZonedDateTime thirtyOneDaysLater = zdt.plus( Period.ofDays( 31 ) ) ;
thirtyOneDaysLater.toString(): 2015-09-18T00:00+12:00[Pacific/Auckland]
If your business logic is really intending a calendar month rather than a specific number of days, use a different Period
. The class makes adjustments as needed to handle various months’ length (read the doc and follow that doc’s link).
ZonedDateTime monthLater = zdt.plus( Period.ofMonths( 1 ) ) ;
monthLater.toString(): 2015-09-18T00:00+12:00[Pacific/Auckland]
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.
Using a JDBC driver compliant with JDBC 4.2 or later, you may exchange java.time objects directly with your database. No need for strings nor java.sql.* classes.
Where to obtain the java.time classes?
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.