Easiest way to set past/future date in Java 8 [duplicate] - java

This question already has an answer here:
Setting future date in Java 8
(1 answer)
Closed 4 years ago.
I have a solution for setting future/past date Java 8, but I would like to know if there is a cleaner way.
I have a method in which one of the argument is of type ZonedDateTime.
I am extracting the time, converting to milliseconds and subtracting that from present now.
void setFuturePastDate(ZonedDateTime dateTime) {
long diffInSeconds = ZonedDateTime.now().toEpochSecond()
- dateTime.toEpochSecond();
Duration durationInSeconds = Duration.ofSeconds(diffInSeconds);
Instant instantInSeconds = now.minusSeconds(durationInSeconds);
Clock clock = Clock.fixed(instantInSeconds, ZoneId.systemDefault());
System.out.println(ZonedDateTime.now(clock)); // - I have a past date
In Joda it was simple:
setCurrentMillisSystem(long)
and wherever we access new DateTime() it will give the date set.
Is there a cleaner way in Java 8 ?

void setFuturePastDate(ZonedDateTime dateTime) {
Clock clock = Clock.fixed(dateTime.toInstant(), ZoneId.systemDefault());
System.out.println(ZonedDateTime.now(clock)); // - I have a past date
}
This method prints the same ZonedDateTime as I passed in (provided it has the default zone).

If I understood you correctly, this is what you want:
void setFuturePastDate(LocalDateTime dateTime){
final LocalDateTime now = LocalDateTime.now();
final Duration duration = Duration.between(now, dateTime);
final LocalDateTime mirrored;
if(duration.isNegative()){
mirrored = now.minus(duration);
} else {
mirrored = now.plus(duration);
}
System.out.println(mirrored);
}
This mirrors the dateTime around the now(). E.g: 5 days in the past becomes 5 days in the future.

Related

Return ISO-8601 time format in days from Epoch time in Java

I have some Java code which returns the ISO-8601 time format from a given epoch time.
public String getISO8601(String epochTime) {
long epoch = Long.parseLong(epochTs);
ZoneId zone = ZoneId.of("Europe/London");
LocalDate then = Instant.ofEpochMilli(epoch).atZone(zone).toLocalDate();
LocalDate today = LocalDate.now(zone);
Period diff = Period.between(then, today);
return diff.toString();
}
When I pass epochTime to it: 1512259200000
This epoch time is: Sun 2017-12-03 00:00:00
So the method getISO8601 will return: P1Y
This is great! But is there any way I can make sure it will always and only return in days... for example: P365D (instead of: P1Y)
Unfortunately Period doesn't allow the units to be specified, but you can use the until method to handle this, specifying you want the difference in days:
public static Period getPeriodInDaysBetween(LocalDate from, LocalDate to) {
int days = (int) from.until(to, ChronoUnit.DAYS);
return Period.ofDays(days);
}
Use that instead of Period.between and it'll do what you want, I believe.
(The first line is equivalent to the ChronoUnit.DAYS.between(date1, date2) in MS90's answer. Use whichever you find more readable.)
Sure, take a look at following code:
public static long countDays(LocalDate date1, LocalDate date2) {
long daysInAPeriod = ChronoUnit.DAYS.between(date1, date2);
return daysInAPeriod;
}
Period has a getDays method which returns an int number of days in the Period.

How to calculate the time difference in seconds? [duplicate]

This question already has answers here:
Java 8: Calculate difference between two ZonedDateTime
(3 answers)
Closed 5 years ago.
I have two Datetime strings:
val formatter = DateTimeFormatter.ofPattern("yyyy-MMM-dd-hh-mm-ss")
val startTime = formatter format ZonedDateTime.now(ZoneId.of("UTC"))
//...
val endTime = formatter format ZonedDateTime.now(ZoneId.of("UTC"))
How can I calculate the difference in seconds between endTime and startTime?
Use a java.time.temporal.ChronoUnit:
// difference in seconds
ChronoUnit.SECONDS.between(startTime, endTime)
But startTime and endTime must be ZonedDateTime objects, not Strings.
Just keep in mind that the result is floor-rounded - if the real difference is, let's say, 1999 milliseconds, the code above will return 1 (because 1999 milliseconds are not enough to make 2 seconds).
Another detail is that you can use ZoneOffset.UTC instead of ZoneId.of("UTC"), as the result is the same.
Actually, if you're working with UTC, why not use Instant.now() instead? The between method above works the same way with Instant's:
val start = Instant.now()
val end = Instant.now()
val diffInSecs = ChronoUnit.SECONDS.between(start, end)

How to check whether a date is more than 30 days old? [duplicate]

This question already has answers here:
How do I get the date of 31 days ago?
(3 answers)
Closed 6 years ago.
I have a java.util.Date which I need to check whether it is more than 30 days. What is the best way to check that out?
for(Date date: listOfDates) {
// how to check this date to see whether it is more than 30 days limit
if(checkDateLimit()) {
}
}
I am on Java 7.
It depends on how formal you want to be about the definition of "30 days." If all you want to know is whether the given date (which, in Java, includes time down to the millisecond) is 30 days (to the millisecond) old, then you can calculate how many milliseconds there are in 30 days and see if the current date is more than that number of milliseconds larger than the given date.
Dates reveal their millisecond values through getTime().
private boolean olderThan30Days(Date givenDate)
{
long currentMillis = new Date().getTime();
long millisIn30Days = 30 * 24 * 60 * 60 * 1000;
boolean result = givenDate.getTime() < (currentMillis - millisIn30Days);
return result;
}
If you can use Java 8, you can do:
boolean checkDateLimit(Date date) {
// convert Date into Java 8 LocalDate
LocalDate localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
LocalDate today = LocalDate.now();
// count number of days between the given date and today
long days = ChronoUnit.DAYS.between(localDate, today);
return days > 30;
}
As recommended by others, you should use JodaTime:
private static boolean olderThan30Days(Date givenDate) {
boolean result =
Days.daysBetween(new DateTime(givenDate), new DateTime()).isGreaterThan(Days.days(30));
return result;
}

Duration.ofDays generates UnsupportedTemporalTypeException

I am trying to learn the new Date & Time API. My code is working except for the last line:
LocalDate current=LocalDate.now();
System.out.println(current);
LocalDate personaldate=LocalDate.of(2011,Month.AUGUST, 15);
System.out.println(personaldate);
LocalDate afterten=current.plus(Period.ofDays(10));
System.out.println(afterten);
// error occurs here
System.out.println(afterten.plus(Duration.ofDays(3)));
When I try and add a Duration in days, it generates an error. Can anyone help me understand why?
Error:
Exception in thread "main" java.time.temporal.UnsupportedTemporalTypeException: Unsupported unit: Seconds
at java.time.LocalDate.plus(LocalDate.java:1241)
at java.time.LocalDate.plus(LocalDate.java:137)
at java.time.Duration.addTo(Duration.java:1070)
at java.time.LocalDate.plus(LocalDate.java:1143)
at TestClass.main(TestClass.java:15)
Whilst the accepted answer is completely correct, when I arrived at this question, I was looking for a simple solution to my problem.
I found using Period would not allow me to count the number of days between my two LocalDate objects. (Tell me how many years, months and days between the two, yes, but not just then number of days.)
However, to get the result I was after was as simple as adding the LocalDate method "atStartOfDay" to each of my objects.
So my erronious code:
long daysUntilExpiry = Duration.between(LocalDate.now(), training.getExpiryDate()).toDays();
was simply adjusted to:
long daysUntilExpiry = Duration.between(LocalDate.now().atStartOfDay(), training.getExpiryDate().atStartOfDay()).toDays();
Doing this make the objects into LocalDateTime objects which can be used with Duration. Because both object have start of day as the "time" part, there is no difference.
Hope this helps someone else.
A Duration measures an amount of time using time-based values (seconds, nanoseconds). A Period uses date-based values (years, months, days).
here is the link
https://docs.oracle.com/javase/tutorial/datetime/iso/period.html
the same as in JodaTime
//(year,month,day)
LocalDate beginDate = LocalDate.of(1899,12,31);
LocalDate today = LocalDate.now();
ChronoUnit.DAYS.between(beginDate, today)
As hinted before, Duration is always seconds-based whereas Period honours the day as concept.
The code throws an exception when it tries to add seconds on a LocalDate - which is also day-based.
Changing your code like this shows the difference: use LocalDateTime when getting down to instants within days:
LocalDateTime current = LocalDateTime.now();
System.out.println(current);
LocalDateTime afterten = current.plus(Period.ofDays(10));
System.out.println(afterten);
// error occurred here - but with LocalDateTime is resolved!
System.out.println(afterten.plus(Duration.ofDays(3)));
Try to run following code in a Unit test and see for yourself that the accepted answer to your problem should be ChronoUnit.DAYS.between() as stated by Ravi.
LocalDate date1 = LocalDate.of(2020,6,2);
LocalDate date2 = LocalDate.of(2020,7,4);
System.out.printf("ChronoUnit.DAYS = %d%n", ChronoUnit.DAYS.between(date1, date2));
System.out.printf("Period.between = %d%n",Period.between(date1, date2).getDays());
Because the output will look as follows:
ChronoUnit.DAYS = 32
Period.between = 2
Period will incorrectly return only the days portion of the difference (ignoring higher order differences like months and years).
System.out.printf("Duration.between = %d%n",Duration.between(date1, date2).getSeconds());
This will throw an exception as LocalDate does not provide enough information for seconds calculations (undefined hour, minutes and seconds).
Therefore you would have to convert it to LocalDateTime for example by calling date1.atStartOfDay().
System.out.printf("Duration.between = %d%n",Duration.between(date1.atStartOfDay(), date2.atStartOfDay()).get(ChronoUnit.DAYS));
This call will simply throw java.time.temporal.UnsupportedTemporalTypeException: Unsupported unit: Days because of how the get method on Duration class is implemented in Java:
#Override
public long get(TemporalUnit unit) {
if (unit == SECONDS) {
return seconds;
} else if (unit == NANOS) {
return nanos;
} else {
throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit);
}
}

Java date/calendar ignoring time zone [duplicate]

This question already has answers here:
Date and time conversion to some other Timezone in java
(11 answers)
Closed 8 years ago.
How to ignore timezone in dates? I mean I seted some jsf input with 8:54 with format HH:mm, and in setter I am getting 9:54, i Think that is because of time zone GMT+1. How to convert this date to ignore time zone? How to convert it when i dont know from which time zone I am using it.
code, setter of time picker input:
public void setDateTest(Date hmm){
if (hmm!=null){
int a = hmm.getHours();
int b = hmm.getMinutes();
Calendar cal = Calendar.getInstance();
cal.get(Calendar.ZONE_OFFSET);
cal.setTime(hmm);
int a2 = cal.get(Calendar.HOUR);
int c2 = cal.get(Calendar.HOUR_OF_DAY);
int b2 = cal.get(Calendar.MINUTE);
}
}
if you are using java.util.Calendar (probably you are), Hour index is in range between 0-11
http://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html#HOUR
so if you are giving 8 for Calendar.HOUR, this is actually 9. This might be the cause. Just an opinion...

Categories