This question already has answers here:
How to create a Date object, using UTC, at a specific time in the past?
(2 answers)
Closed 5 years ago.
How can I return a Date object of 4 hours less than the current system time in Java?
If you're already on Java 8 or newer:
LocalDateTime fourHoursAgo = LocalDateTime.now().minusHours(4);
Or if you want to take DST (Daylight Saving Time) into account (just in case it coincidentally went into or out DST somewhere the last 4 hours):
ZonedDateTime fourHoursAgo = ZonedDateTime.now().minusHours(4);
Or if you're not on Java 8 yet:
Date fourHoursAgo = new Date(System.currentTimeMillis() - (4 * 60 * 60 * 1000));
And you want to take DST into account:
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.HOUR_OF_DAY, -4);
Date fourHoursAgo = calendar.getTime();
The other answers are correct, but I would like to contribute the modern answer. The modern solution uses java.time, the modern Java date and time API.
Instant fourHoursAgo = Instant.now().minus(Duration.ofHours(4));
System.out.println(fourHoursAgo);
This just printed:
2018-01-31T15:22:21.113710Z
The Z in the end indicates that the time is printed in UTC — at UTC offset zero if you will. The Instant class is the modern replacement for Date, so I recommend you stick to it. The modern API is generally so much nicer to work with, so much cleaner, so much better designed.
Please note the advantages of letting the library class do the subtraction of 4 hours for you: the code is clearer to read and less error-prone. No funny constants, and no readers taking time to check if they are correct.
If you do need an old-fashioned Date object, for example when using a legacy API that you cannot change or don’t want to change, convert like this:
Date oldfashionedDate = Date.from(fourHoursAgo);
Link: Oracle Tutorial trail: Date Time. Of course there are other resources on the internet too, please search.
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.HOUR_OF_DAY, -4);
calendar.getTime();
Convert it to milliseconds, subtract the number of milliseconds in 4 hours, convert it back to a Date.
Calendar c = Calendar.getInstance();
c.add(Calendar.HOUR_OF_DAY, -4);
java.util.Date d = c.getTime();
System.out.println(d);
Calendar c =Calendar.getInstance() ;
c.add(Calendar.HOUR,-4);
Date d = c.getTime();
Use a Calendar object and the add method.
calendar.add(Calendar.HOUR, -4);
See http://download.oracle.com/javase/6/docs/api/java/util/Calendar.html
Related
This question already has answers here:
How to set time zone of a java.util.Date?
(12 answers)
Closed 5 years ago.
JVM version is 1.7. Timezone is GMT+3, offset 180 minutes. 1500411600000 corresponds to 7/19/2017, 12:00:00 AM (I've verified this online).
I'm executing the following code to adjust time of a Date instance:
final Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
Date date = new Date(1500411600000L);
calendar.setTime(date);
calendar.set(Calendar.HOUR_OF_DAY, 23);
calendar.set(Calendar.MINUTE, 59);
calendar.set(Calendar.SECOND, 59);
calendar.set(Calendar.MILLISECOND, 999);
date = calendar.getTime();
I expect date to become 7/19/2017, 11:59:59 PM but instead of this I get 7/19/2017, 2:59:59 AM. 3 hours difference - exactly as much as my timezone is different from UTC/GMT, so I suppose that some unnoticed conversion happens here.
Can you please help me to find timezone agnostic code for adjusting time in date?
You are correct that at offset UTC+3 your millisecond value, 1500411600000, corresponds to July 19, 2017 at midnight (start of day). At other offsets it corresponds to other times of day either July 18 or 19.
java.time
Assuming that it is no coincidence that you have got midnight in your own time zone, that the value is really supposed to represent a date, not a time, I recommend you use LocalDate from java.time to represent it:
ZoneId yourTimeZone = ZoneId.of("Europe/Riga");
LocalDate date = Instant.ofEpochMilli(1500411600000L)
.atZone(yourTimeZone)
.toLocalDate();
System.out.println(date);
This prints the expected
2017-07-19
Please either substitute your correct time zone in case it doesn’t happen to be Europe/Riga, or use a ZoneOffset instead: .atOffset(ZoneOffset.ofHoursMinutes(3, 0)) (the other lines are the same).
I suspect you don’t really want the end of the day even though in your question you are trying to set it. If this is for determining whether some point in time is before the end of the day, compare it to the start of the following day and require that it is strictly before. This saves you the trouble with the odd-looking minutes, seconds and fractions of second.
ZonedDateTime startOfNextDay = date.plusDays(1).atStartOfDay(yourTimeZone);
java.time came out in 2014 as a replacement for both the poorly designed date and time classes from Java 1.0 and 1.1 and for Joda-Time, from which much inspiration was drawn. I warmly recommend you use it.
What you tried in the question
I believe your code from the question is also clearer when expressed with java.time:
OffsetDateTime endOfDay = Instant.ofEpochMilli(1500411600000L)
.atOffset(ZoneOffset.UTC)
.with(LocalTime.MAX);
System.out.println(endOfDay);
This prints
2017-07-18T23:59:59.999999999Z
(July 18 at the end of day in UTC; Z at the end denotes UTC). Except for the number of decimals, this is also the result you got. You may have been fooled by the fact that your Date instance is printed something like Wed Jul 19 02:59:59 EEST 2017 (the time zone abbreviation depending on your JVM’s time zone setting). Date.toString() grabs your JVM’s time zone setting and converts the date-time to this time zone for the generated string only; the Date instance itself is not modified and only holds a point on the time line, no time zone.
Question: can I use java.time with my Java version?
Yes you can. You just need to use at least Java 6.
In Java 8 and later the new API comes built-in.
In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (ThreeTen for JSR 310).
On Android, use the Android edition of ThreeTen Backport. It’s called ThreeTenABP, and there’s a thorough explanation in this question: How to use ThreeTenABP in Android Project.
For learning to use java.time, see the Oracle tutorial or find other resoureces on the net.
You're using Calendar.getInstance(TimeZone.getTimeZone("UTC")), but you have to use the timezone you're in. As you stated GMT+3
Please refer to this thread here which explains the issue regarding Date and timezones.
How to set time zone of a java.util.Date?
The Date object will have the correct adjusted time but when it is displayed, the output will use your local timezone. You can forcefully set the timezone of your JVM using the following code but this may have unintended consequences in other parts of your code.
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
In an ideal world you would use the Java 8 date classes or Joda time library classes both of which provide some simple date manipulation methods.
Java 8 date classes
Use clear. It seems a historical "bug" to me, a time zoned Calendar, where setTime does not alter the zone.
final Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
Date date = new Date(1500411600000L);
calendar.clear(); // To reset _all_ fields, incl. the time zone offset ZONE_OFFSET.
calendar.setTime(date);
calendar.set(Calendar.HOUR_OF_DAY, 23);
calendar.set(Calendar.MINUTE, 59);
calendar.set(Calendar.SECOND, 59);
calendar.set(Calendar.MILLISECOND, 999);
date = calendar.getTime();
Of course this might be the right argument to switch to the new java time API.
The problem is bigger than described in my question. It stems from incorrect managing Date/Time for user's timezone. In my application timestamp was sent in user's timezone and then evaluated to date in server's timezone, but timezone difference was not taken into account. I tried to fix this and faced the issue described in the question.
I listened to the #ThomasEdwin's advice to use Joda Time and I'm happy to share this solution:
long userTimezoneOffset = 180; // it's a parameter submitted by client app
Date date = new Date(1500411600000L); // it's another parameter submitted by client app
final DateTimeZone zone = DateTimeZone.forOffsetMillis((int) TimeUnit.MINUTES.toMillis(userTimezoneOffset));
final DateTimeZone serverZone = DateTimeZone.getDefault();
MutableDateTime dateTime = new MutableDateTime(date, zone);
dateTime.setHourOfDay(23);
dateTime.setMinuteOfHour(59);
dateTime.setSecondOfMinute(59);
dateTime.setMillisOfSecond(999);
dateTime.setZoneRetainFields(serverZone);
date = dateTime.toDate();
// now date.toString() returns expected result
Also I found -Duser.timezone JVM parameter to be quite useful when debugging this issue. See here for a list of supported timezone IDs.
Is there any way to update only a Date's time path?
I tried Date.setTime() but it replaces the date path too. I there any java method or the only way is to set hour, minute, second and milisecond?
Thank you
A Java Date is just a wrapper around a long that counts time from the epoch (January 1, 1970). Much more flexible is Calendar. You can create a Calendar from a Date:
Date date = . . .;
Calendar cal = new GregorianCalendar();
cal.setTime(date);
Then you can set various fields of the Calendar:
cal.set(Calendar.HOUR_OF_DAY, 8);
// etc.
I would start by moving away from java.util.Date entirely. Ideally, use Joda Time as it's a far more capable date/time library.
Otherwise, you should use java.util.Calendar. A java.util.Date doesn't have a particular date/time until you decide what time zone you're interested in - it just represents an instant in time, which different people around the world will consider to be a different date and time of day.
You'll want to take a look at java.util.Calender.
It will allow you to change the individual parts of the date/time.
Calendar cal = Calender.getInstance();
cal.setTime(date);
cal.set(Calender.HOUR, hour);
Alternatively, as has already being suggested, I'd take a look at Joda Time
I have found some similar Que's on SO but had not find the solution.
I have today's Date as following: (Let's say this as Date1 and it's value as 2012-06-22)
Calendar cal = Calendar.getInstance();
SimpleDateFormat dateformatter = new SimpleDateFormat("yyyy-MM-dd");
Date start = cal.getTime();
String currentDate=dateformatter.format(start);
I'm retrieving 4 values from the user:
Particular Date (Assume 5)
Particular Month (Assume 1)
Particular Year (Assume 2012)
No. of days (Assume 7)
So this date, say Date2 becomes 2012-01-05 (yyyy-MM-dd) along with No. of days set to 7.
I want to compare Date 1 and Date 2-No. of days.
I know that by using following snippet, particular no. of days can be subtracted from a calender instance.
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DATE, -7);
But since I'm having Date2 in form of String, I'm not able to follow this approach.
Any help appreciated.
Edit:
From your suggestions, I'll be able to convert String to Date by using parse method of SimpleDateFormat.
Now I've 2 Date Objects.
How do I find Difference between them in terms of days, months, and years?
How to Subtract particular no. of days, say 7, from a particular date, say 2012-01-05?
java.time
The question and the accepted answer have used the java.util Date-Time API and their parsing/formatting API, SimpleDateFormat which was appropriate thing to do using the standard library in 2012. In March 2014, Java 8 introduced the modern Date-Time API which supplanted the legacy API and since then it is highly recommended to use the modern Date-Time API.
Also, quoted below is a notice from the home page of Joda-Time:
Note that from Java SE 8 onwards, users are asked to migrate to java.time (JSR-310) - a core part of the JDK which replaces this project.
Requirements copied from your question:
From your suggestions, I'll be able to convert String to Date by using
parse method of SimpleDateFormat.
Now I've 2 Date Objects.
How do I find Difference between them in terms of days, months, and
years?
How to Subtract particular no. of days, say 7, from a
particular date, say 2012-01-05?
Solution using java.time, the modern Date-Time API:
With java.time, you can parse your date string into a LocalDate and then find the Period between this date and the current date (which you obtain with LocalDate.now()). You can also subtract days, months, and years using methods like minusXxx/minus. You have similar methods (plusXxx/plus) for adding these units. Check the documentation of LocalDate to learn more about it.
Note: java.time API is based on ISO 8601 and therefore you do not need a DateTimeFormatter to parse a date-time string which is already in ISO 8601 format (e.g. your date-time string, 2012-06-22).
Demo:
import java.time.LocalDate;
import java.time.Period;
import java.time.temporal.ChronoUnit;
class Main {
public static void main(String[] args) {
LocalDate then = LocalDate.parse("2012-06-22");
LocalDate now = LocalDate.now();
Period period = Period.between(then, now);
System.out.println(period);
System.out.printf("%d years %d months %d days%n",
period.getYears(), period.getMonths(), period.getDays());
// Examples of subtracting date units
LocalDate sevenDaysAgo = now.minusDays(7);
System.out.println(sevenDaysAgo);
// Alternatively
sevenDaysAgo = now.minus(7, ChronoUnit.DAYS);
System.out.println(sevenDaysAgo);
}
}
Output from a sample run:
P10Y6M27D
10 years 6 months 27 days
2023-01-11
2023-01-11
ONLINE DEMO
Learn more about the modern Date-Time API from Trail: Date Time.
use SimpleDateFormat to convert String (representing date) to Date
For example :
Date parsedDate = new SimpleDateFormat("yyyy-MM-dd").parse("2012-01-05");
If you can possibly use Joda Time instead of Date/Calendar, do so. It'll make your life easier.
If not, it sounds like you don't want to format the current date - instead, you want to parse Date2 from the user:
Date date2 = dateFormatter.parse(text);
Then you can either create a calendar and subtract a particular number of days, or (if you're talking about elapsed time - you need to think about your behaviour around DST transitions and time zones here) you could just subtract 7 * 24 * 60 * 60 * 1000 milliseconds from date2.getTime().
Fundamentally, you should convert out of a string format as earlier as possible, and only convert to a string format when you really need to - certainly not for comparisons. The natural representation of this data is as a Date or Calendar (assuming you're sticking with the JDK), so work towards getting your data into that representation.
You have several genuine "business" questions to think about though:
Do you want to compare the current date with the date the user's given, or the current date and time with the date the user's given?
What time zone do you want to use for the user's input?
Are you thinking about elapsed days or "logical" days? Because 7 * 24 hours earlier than 1.30am may be 2.30am or vice versa, due to DST transitions
You should answer all those questions before you try to implement your code, as it will affect the representation you use. Also, write unit tests for everything you can think of before you start the implementation.
From my understanding you have two dates now and you want to subtract a particular number of days from date.
First you can use SimpleDateFormat to convert a date to string and string to date
Now to subtract days say 7. you can get time of the date and subtract 7*24*60*60*1000 from it
long daybeforeLong = 7 * 24 * 60 * 60 * 1000;
try {
Date todayDate = new Date();
long nowLong = todayDate.getTime();
Date beforeDate = new Date((nowLong - daybeforeLong));
}
catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
I think you can make use of Comparator provided by java will do work of comparing and sorting the dates too.
here is the link
hope you get what you was looking for..
I have a report created in Jasper Reports which ONLY recognizes java.util.Date's (not Calendar or Gregorian, etc).
Is there a way to create a date 7 days prior to the current date?
Ideally, it would look something like this:
new Date(New Date() - 7)
UPDATE: I can't emphasize this enough: JasperReports DOES NOT RECOGNIZE Java Calendar objects.
From exactly now:
long DAY_IN_MS = 1000 * 60 * 60 * 24;
new Date(System.currentTimeMillis() - (7 * DAY_IN_MS))
From arbitrary Date date:
new Date(date.getTime() - (7 * DAY_IN_MS))
Edit: As pointed out in the other answers, does not account for daylight savings time, if that's a factor.
Just to clarify that limitation I was talking about:
For people affected by daylight savings time, if by 7 days earlier, you mean that if right now is 12pm noon on 14 Mar 2010, you want the calculation of 7 days earlier to result in 12pm on 7 Mar 2010, then be careful.
This solution finds the date/time exactly 24 hours * 7 days= 168 hours earlier.
However, some people are surprised when this solution finds that, for example, (14 Mar 2010 1:00pm) - 7 * DAY_IN_MS may return a result in(7 Mar 2010 12:00pm) where the wall-clock time in your timezone isn't the same between the 2 date/times (1pm vs 12pm). This is due to daylight savings time starting or ending that night and the "wall-clock time" losing or gaining an hour.
If DST isn't a factor for you or if you really do want (168 hours) exactly (regardless of the shift in wall-clock time), then this solution works fine.
Otherwise, you may need to compensate for when your 7 days earlier doesn't really mean exactly 168 hours (due to DST starting or ending within that timeframe).
Use Calendar's facility to create new Date objects using getTime():
import java.util.GregorianCalendar;
import java.util.Date;
Calendar cal = new GregorianCalendar();
cal.add(Calendar.DAY_OF_MONTH, -7);
Date sevenDaysAgo = cal.getTime();
try
Date sevenDay = new Date(System.currentTimeMillis() - 7L * 24 * 3600 * 1000));
Another way is to use Calendar but I don't like using it myself.
Since no one has mentioned TimeUnit yet:
new Date(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(7))
Java 8 based solution:
new Date(
Instant.now().minus(7, ChronoUnit.DAYS)
.toEpochMilli()
)
Try this:
Calendar c = Calendar.getInstance();
c.add(Calendar.DAY_OF_MONTH, -7);
return c.getTime();
A determining "days" requires a time zone. A time zone defines when a "day" begins. A time zone includes rules for handling Daylight Saving Time and other anomalies. There is no magic to make time zones irrelevant. If you ignore the issue, the JVM's default time zone will be applied. This tends to lead to confusion and pain.
Avoid java.util.Date
The java.util.Date and .Calendar classes are notoriously troublesome. Avoid them. They are so bad that Sun/Oracle agreed to supplant them with the new java.time package in Java 8. Use either that or Joda-Time.
Joda-Time
Example code in Joda-Time 2.3.
DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" ); // Specify or else the JVM's default will apply.
DateTime dateTime = new DateTime( new java.util.Date(), timeZone ); // Simulate passing a Date.
DateTime weekAgo = dateTime.minusDays( 7 );
First Moment Of Day
Or, you may want to adjust the time-of-day to the first moment of the day so as to capture an entire day's worth of time. Call the method withTimeAtStartOfDay. Keep in mind this is usually 00:00:00 but not always.
Avoid the "midnight" methods and classes in Joda-Time. They are based on a faulty concept and are now deprecated.
DateTime dateTimeStart = new DateTime( new java.util.Date(), timeZone ).withTimeAtStartOfDay(); // Not necessarily the time "00:00:00".
DateTime weekAgo = dateTime.minusDays( 7 ).withTimeAtStartOfDay();
Convert To/From j.u.Date
As seen above, to convert from java.util.Date to Joda-Time merely pass the Date object to constructor of DateTime. Understand that a j.u.Date has no time zone, a DateTime does. So assign the desired/appropriate time zone for deciding what "days" are and when they start.
To go the other way, DateTime to j.u.Date, simply call the toDate method.
java.util.Date date = dateTime.toDate();
I'm not sure when they added these, but JasperReports has their own set of "functions" that can manipulate dates. Here is an example that I haven't tested thoroughly:
DATE(YEAR(TODAY()), MONTH(TODAY()), DAY(TODAY()) - 7)
That builds a java.util.Date with the date set to 7 days from today. If you want to use a different "anchor" date, just replace TODAY() with whatever date you want to use.
You can try this,
Calendar c = Calendar.getInstance();
c.add(Calendar.DAY_OF_MONTH, -7);
System.out.println(new java.sql.Date(c.getTimeInMillis()));
Due to the heated discussion:
The question may not have a proper answer w/o a designated timezone.
below it is some code to work w/ the default (and hence deprecated) timezone that takes into account the default timezone daylight saving.
Date date= new Date();
date.setDate(date.getDate()-7);//date works as calendar w/ negatives
While the solution does work, it is exactly as bogus as in terms of assuming the timezone.
new Date(System.currentTimeMillis() - 10080*60000);//a week has 10080 minutes
Please, don't vote for the answer.
I'm doing it this way :
Date oneWeekAgo = DateUtils.addDays(DateUtils.truncate(new Date(), java.util.Calendar.DAY_OF_MONTH), -7);
This question already has answers here:
How can I get the current date and time in UTC or GMT in Java?
(33 answers)
Closed 6 years ago.
Since java.util.Date is mostly deprecated, what's the right way to get a timestamp for a given date, UTC time? The one that could be compared against System.currentTimeMillis().
Using the Calendar class you can create a time stamp at a specific time in a specific timezone. Once you have that, you can then get the millisecond time stamp to compare with:
Calendar cal = new GregorianCalendar();
cal.set(Calendar.DAY_OF_MONTH, 10);
// etc...
if (System.currentTimeMillis() < cal.getTimeInMillis()) {
// do your stuff
}
edit: changed to use more direct method to get time in milliseconds from Calendar instance. Thanks Outlaw Programmer
The "official" replacement for many things Date was used for is Calendar. Unfortunately it is rather clumsy and over-engineered. Your problem can be solved like this:
long currentMillis = System.currentTimeMillis();
Date date = new Date(currentMillis);
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
long calendarMillis = calendar.getTimeInMillis();
assert currentMillis == calendarMillis;
Calendars can also be initialized in different ways, even one field at a time (hour, minute, second, etc.). Have a look at the Javadoc.
Although I didn't try it myself, I believe you should take a look at the JODA-Time project (open source) if your project allows external libs.
AFAIK, JODA time has contributed a lot to a new JSR (normally in Java7) on date/time.
Many people claim JODA time is the solution to all java.util.Date/Calendar problems;-)
Definitely worth a try.
Take a look at the Calendar class.
You can make a Data with the current time (not deprecated) and then make Calendar from that (there are other ways too).