While I cannot speak to the PHP portion of your Question, I can correct your Java code.
tl;dr
Duration.between(
LocalDate.of( 2017 , Month.NOVEMBER , 5 ).atStartOfDay( ZoneId.of( "America/New_York" ) ) ,
LocalDate.of( 2017 , Month.NOVEMBER , 5 ).plusDays( 1 ).atStartOfDay( ZoneId.of( "America/New_York" ) )
).toString()
PT25H
Duration.between(
LocalDate.of( 2017 , Month.NOVEMBER , 5 ).atStartOfDay( ZoneOffset.UTC ) ,
LocalDate.of( 2017 , Month.NOVEMBER , 5 ).plusDays( 1 ).atStartOfDay( ZoneOffset.UTC )
).toString()
PT24H
A day in UTC is always 24-hours in length. A day in some time zones may be 23, 24, 25 or some other number of hours, and may even include a partial (fractional) hour.
Details
You are using the wrong classes for Java, and you were ignoring the crucial issue of time zone. The java.util.Date
class is confusing, troublesome, and fortunately, now legacy. The modern java.time classes supplant those old date-time classes.
You ignore the crucial issue of time zone in your example code. That legacy Date
class is always in UTC, but you care about America/New_York
time zone. Your code is calculating 24 hours for a generic 24-hour day (UTC) while actually the 2017-11-05 in America/New_York
is 25 hours rather than 24.
Your example code for Java makes no sense to me, as you are calculating a duration in milliseconds and then dividing by 24. I do not see how that division helps.
The number of milliseconds in a generic 24 hour day = ( 24 * 60 * 60 * 1,000 ) = 86400000. That is number returned by your code using java.util.Date
if we eliminate the division by 24.
long millis = ((new Date(2017, 11, 6).getTime()) - (new Date(2017, 11, 5).getTime())) ;
System.out.println( millis );
86400000
See that code run live at IdeOne.com.
LocalDate
The LocalDate
class represents a date-only value without time-of-day and without time zone.
LocalDate ld = LocalDate.of( 2017 , Month.NOVEMBER , 5 ) ;
Time zone
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.
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/New_York" ) ;
ZonedDateTime
Let java.time determine the first moment of the day. Do not assume the day starts at 00:00. Anomalies such as Daylight Saving Time (DST) mean the day may start at a time such as 01:00.
ZonedDateTime start = ld.atStartOfDay( z ) ;
Usually the Half-Open approach is best for defining a span of time. In this approach the beginning is inclusive while the ending is exclusive. So a full day is defined as starting at the first moment of the day and running up to, but not including, the first moment of the following day.
ZonedDateTime stop = ld.plusDays( 1 ).atStartOfDay( z ) ;
Calculate the length of that day, November 5th in New York zone.
Duration d = Duration.between( start , stop ) ;
PT25H
So, yes, we see a day that is 25 hours long because of the DST cut-over.
See this code run live at IdeOne.com.
That output from Duration::toString
is in standard ISO 8601 format.
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?
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.