I'm trying to get the total amount of Milliseconds (not the millis field) from the Period object instance. I've tried multiple conversions, as I couldn't find any method easily giving it.
Has anyone ever needed that and managed to retrieve it ?
(I need this for my patch, to figure out a negative period; negative millis = negative period.)
You can't get the millis directly from a Period, since fields like months and years are variable in terms of milliseconds.
In order to make this work, you need to supply a "baseline" instant from which Period can calculate that actual millisecond duration.
For example, the Period.toDurationFrom and Period.toDurationTo methods take such a baseline instant, and calculate a Duration object, which you can then obtain the millis.
The Javadoc for toDurationFrom says:
Gets the total millisecond duration of this period relative to a start instant.
This method adds the period to the specified instant in order to calculate the duration.
An instant must be supplied as the duration of a period varies. For example, a period of 1 month could vary between the equivalent of 28 and 31 days in milliseconds due to different length months. Similarly, a day can vary at Daylight Savings cutover, typically between 23 and 25 hours.
So you need to pick an appropriate baseline instant for your application.
If you want to get the millis from a specific time it can be done by using the plus() or minus() methods of the DateTime class.
e.g. getting the millis from now
DateTime start = new DateTime(); //NOW
DateTime end = start.plus(<your period>);
long millis = end.getMillis() - start.getMillis();
Using Joda time 2.3, it is:
toStandardDuration().getMillis()
Related
How do I get java time millis in UTC ignoring the minutes and seconds.
For instance :
If it is October 10 2019, 1:10:59 AM , it should get the Time or millis for
October 10 2019, 1 AM.
Summary:
Instant
.now()
.truncatedTo(
ChronoUnit.HOURS
)
.toEpochMilli()
1570600800000
java.time, the modern Java date and time API has got exactly the method you need: many of the classes have a truncatedTo method for needs like yours.
Instant now = Instant.now();
System.out.println("Rough milliseconds: " + now.toEpochMilli());
Instant currentWholeHour = now.truncatedTo(ChronoUnit.HOURS);
System.out.println("Milliseconds ignoring minutes and seconds: "
+ currentWholeHour.toEpochMilli());
When running this snippet just now the output was:
Rough milliseconds: 1570604053787
Milliseconds ignoring minutes and seconds: 1570600800000
I know very well that the first line is what you asked not to have. I only included it for you to see the difference.
The truncation happens in UTC. If you are in a time zone whose offset is not a whole number of hours from UTC, the results may not be as you had expected. Examples of such time zones include Asia/Kathmandu, America/St_Johns some of the year also Australia/Lord_Howe.
Link: Oracle tutorial: Date Time
You can use LocalDate#atTime:
LocalDate.now().atTime(LocalDateTime.now().getHour(), 0, 0);
This will give you current date with hour and minutes and seconds set to 0.
And to get milliseconds in UTC:
LocalDate.now().atTime(LocalDateTime.now().getHour(), 0, 0).toInstant(ZoneOffset.UTC).toEpochMilli();
Jon Skeet notices, that calling now might give unexpected results in corner cases. To be sure, we can call it once and then convert it to LocalDate with mentioned solution:
var currentTime = LocalDateTime.now();
var currentDate = currentTime.toLocalDate();
Or the other way around - get LocalDate first and use LocalDate#atStartOfDay.
Given that you're interested in UTC milliseconds, and there are a whole number of milliseconds per hour, you can do this with simple arithmetic. For most calendrical computations I really wouldn't recommend that, but in this case I think it's the simplest approach. Something like this:
private static final long MILLISECONDS_PER_HOUR = TimeUnit.HOURS.toMillis(1);
// Injecting a clock makes the method testable. You can use Clock.systemUTC()
// for the system clock.
public static long truncateMillisToHour(Clock clock) {
long millisSinceEpoch = clock.millis();
// Truncate to the nearest hour
long hoursSinceEpoch = millisSinceEpoch / MILLISECONDS_PER_HOUR;
// Then multiply up again
return hoursSinceEpoch * MILLISECONDS_PER_HOUR;
}
Note that if the clock is for before the epoch, this will round up to the nearest hour, but if you're taking the genuine "current time" then that's unlikely to be a problem.
(I wrote this answer before seeing Ole V.V.'s answer with truncatedTo, which is a very nice approach.)
I want to get a difference in hours between a current time in a specific timezone and UTC time. I tried this:
LocalTime time = LocalTime.now();
System.out.println(time); //21:05:42:764
LocalTime utcTime = LocalTime.now(ZoneId.of("UTC"));
System.out.println(utcTime); //18:05:42:769
System.out.println(Duration.between(utcTime, time).getSeconds()/3600); //2
System.out.println(Duration.between(time, utcTime).getSeconds()/3600); //-3
Why is the difference between the last two results and are there better ways to do it? I need to get the number 3.
Why is the difference between the last two results
The reason that you're getting different results for the two computed durations is a combination of the fact that there is some tiny amount of time elapsed between the two recordings and the fact that the duration start time is included in the range but the duration end time is not.
Consider these times instead: 6:00:00:001 vs 8:00:00:000. Here it is very obvious that we're only exactly one millisecond off of two hours, but when we think about seconds we're either going to get 7199 or -7200. When we then do integer math (i.e. divide by 3600), we're going to get 1 or -2.
If it weren't for the one extra millisecond on the first timestamp, the absolute value of the two would be identical.
Duration is the wrong class. There is zero duration between "now" in one time zone and "now" in another. For a fun but memorable way to think about this, see here.
You appear to be seeking to know the current offset from UTC for a given time zone. You can use the ZonedDateTime class for that:
ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("Asia/Kolkata"));
ZoneOffset offset = zdt.getOffset();
int offsetMinutes = offset.getTotalSeconds() / 60;
double offsetHours = ((double) offsetMinutes) / 60;
System.out.println(offsetHours); // 5.5
You could also just use ZonedDateTime.now() on the first line, if you want to use the computer's current time zone.
With regard to LocalTime - that is just the time portion (hours, minutes, seconds, and smaller). Since there is no date associated, you can't necessarily determine which time zone offset it belongs to. There is more than one date that "today" going on at any given moment. Time zone offsets range from UTC-12 to UTC+14, so there are indeed values where the same time of day is happening on two different dates somewhere on the planet.
As an example, 08:00:00 in Hawaii (Pacific/Honolulu) on 2019-01-01 is also 08:00:00 in Kiribati (Pacific/Kiritimati), but on 2019-01-02 - the following date! (Reference here.) Thus, if you had a LocalTime object with 08:00:00 and it was 08:00:00 in one of those two zones, you'd not be able to tell which one it was, or what the corresponding UTC offset should be.
Also, keep in mind that time zone offsets are not limited to whole hours. There are present-day time zones with half-hour and 45-minute offset. Historically, there have been others.
Lastly, keep in mind that an offset is not necessarily enough to identify a time zone. Many time zones share offsets at some points in time, but differ in others. See "Time Zone != Offset" in the timezone tag wiki.
Oh, and about your results getting 2 in one direction and -3 in the other - this is a rounding error due to your integer division. If you print out the seconds value, you'll notice they are one second apart (10799, vs -10800). Dig closer and you'll find that "now" included fractional seconds that were truncated with the getSeconds call. (You called .now() twice, so they were at slightly different times.)
Can someone explain why the following tests fails?
#Test
public void testDuration() {
Duration duration = Duration.standardDays(1);
assertTrue(duration.getStandardMinutes() == 1440); //OK
assertTrue(duration.toPeriod().getMinutes() == 1440); //NOK. result = 0
assertTrue(new Period(duration.getMillis()).getMinutes() == 1400); //NOK. result = 0
}
A Period in JodaTime represents a "set of duration field values". Therefore, the methods getMinutes(), getHours(), ... are returning the value of those fields rather than computing the minutes, hours, ...
Furthermore, the conversion from a Duration sets the fields according to a PeriodType and a chronology.
From the API (http://joda-time.sourceforge.net/apidocs/org/joda/time/ReadableDuration.html#toPeriod%28%29):
Period toPeriod()
Converts this duration to a Period instance using the standard period type and the ISO chronology.
Only precise fields in the period type will be used. Thus, only the hour, minute, second and millisecond fields on the period will be used. The year, month, week and day fields will not be populated.
If the duration is small, less than one day, then this method will perform as you might expect and split the fields evenly. If the duration is larger than one day then all the remaining duration will be stored in the largest available field, hours in this case.
This means, as a Duration's day has exactly 24 hours, all information is stored in the hours field and minutes stays at 0.
See this question for a good explanation of the differences between Interval, Duration and Period.
See here
A period of 1 day is not equal to a period of 24 hours, nor 1 hour equal to 60 minutes. This is because periods represent an abstracted definition of a time period (eg. a day may not actually be 24 hours, it might be 23 or 25 at daylight savings boundary).
I'm going to design an application, in which I need to get the exact time difference between two dates. Ex:
Date1:31/05/2011 12:54:00
Date2:31/05/2011 13:54:00
I tried using getTime() but I didn't get exact result.
The expected output for the above inputs is 3600000 (60 * 60 * 1000) millisec but I'm getting 46800000 (13 * 60 * 60 * 1000).
When I went through different java forums people are suggesting to use JodaTime.
Still I'm unable to get the exact result.
The timezone on I'm working is London(GMT).
Init two dateTime and use Period :
DateTime dt1 = new DateTime(2013,9,11,9,58,56);
DateTime dt2 = new DateTime(2013,9,11,9,58,59);
Period p = new Period(dt1, dt2, PeriodType.millis());
To get difference in milliseconds :
System.out.println(p.getValue(0));
public static long getDiff(Calender cal1, Calender cal2)
{
return Math.abs(cal1.getTimeInMillis() - cal2.getTimeInMillis());
}
Check out secondsBetween( )
Creates a Seconds representing the number of whole seconds between the
two specified partial datetimes.
The two partials must contain the same fields, for example you can
specify two LocalTime objects.
Parameters:
start - the start partial date, must not be null
end - the end partial date, must not be null
Returns:
the period in seconds
JodaTime is using machine time inside. So to find miliseconds, you can use a constant storing LocalDateTime referring to Jan 1, 1970(Because of UNIX Time).
Unix time, or POSIX time, is a system for describing points in time,
defined as the number of seconds elapsed since midnight proleptic
Coordinated Universal Time (UTC) of January 1, 1970, not counting leap
seconds. Then calculate the difference between your DateTime.
I tried like this;
public static void main(String[] args) {
final LocalDateTime JAN_1_1970 = new LocalDateTime(1970, 1, 1, 0, 0);
DateTime local = new DateTime().withZone(DateTimeZone.forID("Europe/Amsterdam"));
DateTime utc = new DateTime(DateTimeZone.UTC);
System.out.println("Europe/Amsterdam milis :" + new Duration(JAN_1_1970.toDateTime(DateTimeZone.forID("Europe/Amsterdam")), local).getMillis());
System.out.println("UTC milis :" + new Duration(JAN_1_1970.toDateTime(DateTimeZone.UTC), utc).getMillis());
}
And the result is;
Europe/Amsterdam milis :1429695646528
UTC milis :1429692046534
And #leonbloy write here a good comment.
Your local and utc represent the same instants of time, (only with
different timezones attached). Hence, getMillis() (which gives the
"physical" time interval elapsed from the "instant" corresponding to
the unix epoch), must return the same value.
Joda is a perfect library but if you need the difference between 2 dates in milliseconds you just should calculate difference between getTime(). If you get wrong results you have some problems with timezones or so. Typically it works.
In Joda-Time 2, what is the difference between the three kinds of time spans:
Period
Interval
Duration
Why do we need three classes?
Which one performs better?
Why is dividing a Period or Duration or Interval instance not implemented? E.g. p = p.divideBy(2);
3 classes are needed because they represent different concepts so it is a matter of picking the appropriate one for the job rather than of relative performance. From the documentation with comments added by me in italics:
An interval in Joda-Time represents an interval of time from one millisecond instant to another instant. Both instants are fully specified instants in the datetime continuum, complete with time zone. Specific times are defined e.g. this might be the interval between 20:00:00GMT yesterday and 09:00:00GMT this morning.
A duration in Joda-Time represents a duration of time measured in milliseconds. The duration is often obtained from an interval. i.e. we can subtract start from end of an interval to derive a duration
A period in Joda-Time represents a period of time defined in terms of fields, for example, 3 years 5 months 2 days and 7 hours. This differs from a duration in that it is inexact in terms of milliseconds. A period can only be resolved to an exact number of milliseconds by specifying the instant (including chronology and time zone) it is relative to. e.g. consider the period of 1 year, if we add this to January 1st we will always arrive at the next January 1st but the duration will depend on whether the intervening year is a leap year or not. Similarly if we add 1 month to the 1st of a month then we will arrive at the 1st of the next month but the duration (in milliseconds) will vary based on the month in question
For question 3, A specific method to divide a duration is not really needed because we can always get the number of milliseconds from the duration as a long (using getMillis()), divide it and construct a new duration (using new Duration(long duration)).
Dividing a period doesn't really have a real meaning based on the definition of a period above. e.g. what is half a month? (its length would depend on which month).
To add to mikej's answer:
A Joda-Time duration is a "physical" time interval; eg:
12000 milliseconds <-- this is a duration
A Joda-Time interval is actually a pair of instants (start instant - end instant). An instant is, again, a "physical" concept, a point in the timeline. Eg (just a possible notation):
(2010/3/3 19:00:00.000 UTC ; 2010/3/3 20:00:00.000 UTC) <-- this is an interval
An interval, then, can be converted to a duration, but not the reverse.
Consider these two intervals:
I1=(2010/3/3 19:00:00.000 UTC ; 2010/3/3 20:00:00.000 UTC)
I2=(2010/3/3 21:00:00.000 UTC ; 2010/3/3 22:00:00.000 UTC)
As intervals, I1 and I2 are different, because the end-points are different; but if I convert them to durations, I get the same thing: 3600000 milliseconds.
(Math analogy: the intervals [10,12] and [95,97] are different intervals, but they have the same length: "interval length" maps to duration).
Finally, a period is a lapse of "civil time", expressed as a number of months, days, hours, etc. It does not -by itself- represent a "physical" interval, hence it can't be directly converted to a duration (months have variable lengths...).
This answers question 3: you can only divide by two a physical time (a duration).