This question already has answers here:
Java - Subtract Days from date [duplicate]
(6 answers)
Closed 8 years ago.
I am trying to do something really simple. I am trying to subtract 2 days from the current day. I get the number of hours from the UI. So in this example, I get 48 hours from the UI. I am doing the following and I don't know what i'm doing wrong here. I think the result of this is it only subtracts a few minutes from the time.
long timeInEpoch = (currentMillis()/1000 - (48 * 60 * 60)); //48 comes from UI
public long currentMillis(){
return new Date().getTime();
}
d = new Date(timeInEpoch * 1000);
I also tried
d1 = new Date(timeInEpoch);
Nothing seems to work. What am I doing wrong here?
try
long millis = System.currentTimeMillis() - 2 * 24 * 60 * 60 * 1000;
Date date = new Date(millis);
it definitely works
Use Calendar API like this to subtract 2 days from a Date object:
Calendar c = Calendar.getInstance();
c.setTime(d);
c.add(Calendar.DATE, -2);
d.setTime( c.getTime().getTime() );
long millisec = d.getTime();
Your code is alright , your variable d should be at offset of 48 hours from the current time on your server.
Make sure the server and your clients are running on the same time otherwise request your server admins to fix the time on your deployment machine.
You would also notice this difference if your client is opening a browser in e.g. Japan and your server is running in USA because of the standard time difference.
try this
long diff = Math.abs(d1.getTime() - d2.getTime());
long diffDays = diff / (2*24 * 60 * 60 * 1000);
Avoid the old java.util.Date and .Calendar classes as they are notoriously troublesome.
Use either Joda-Time or the new Java.time package built into Java 8. Search StackOverflow for hundreds of Questions and Answers on this.
Joda-Time offers methods for adding and subtracting hour, days, and more. The math is done in a smart way, handling Daylight Saving Time nonsense and other issues.
Quick example in Joda-Time 2.7 ( as this is really a duplicate Question, see others for more info ).
DateTimeZone zone = DateTimeZone.forID( "America/Montreal" );
DateTime now = DateTime.now( zone );
DateTime fortyEightHoursAgo = now.minusHours( 48 );
DateTime twoDaysAgo = now.minusDays( 2 );
Related
Instant i1 = Instant.now();
Instant i2 = Instant.now().plusSeconds(60 * 60 * 24 * 365);
Duration<IsoUnit> dur = Duration.from((TemporalAmount) java.time.Duration.between(i1, i2));
System.out.println(dur);
this code prints P365D, is there a way to make units fill up the next bigger unit, so this becomes P1Y and if i had like P334D to P11M and so on?
time4j version is 4.38
The other comments and answers are completely right to say that a year is not always equal to 365 days.
The Time4J-method net.time4j.Duration.from(TemporalAmount) returns a normalized duration using STD_PERIOD as normalizer. The documentation of this normalizer says:
Normalizes the duration items on the base of 1 year = 12 months and 1
day = 24 hours and 1 hour = 60 minutes and 1 minute = 60 seconds -
without converting days to months.
So you can only expect the result to be in days when you start with a temporal amount defined in seconds.
If you still want a year then I suggest you to first convert your instants to calendar dates using an appropriate time zone. But in leap years, your code would still produce 365 days and not a year after having added 60 * 60 * 24 * 365 seconds to the second instant. So your addition of seconds is also flawed because it is based on false assumptions.
Side note:
If you want the reverse way, namely how many seconds are in a year then you might use code like
Moment m1 = Moment.nowInSystemTime();
Moment m2 = m1.toZonalTimestamp(ZonalOffset.UTC).plus(1, CalendarUnit.YEARS).atUTC();
long seconds = SI.SECONDS.between(m1, m2); // = 366 days in seconds if applied on date 2019-05-22!
With a future version of Time4J and possible leap second at the end of year 2019, the code might even produce an extra second.
Anyway, I advise you to update Time4J to v5.4 and consider following mappings:
java.time.Instant as input => net.time4j.MachineTime.from(...)
java.time.LocalDateTime/net.time4j.PlainTimestamp => net.time4j.Duration.from(...)
So if you really want years as possible output in printing durations and you have instants/moments then first convert to LocalDateTime/PlainTimestamp (using a time zone or offset) before you create the appropriate duration object.
Update from 2019-05-25:
Another way with the version v5.4 (or later) is possible via "fuzzy" durations. You could normalize the durations you get by applying an approximation. Example:
Duration<IsoUnit> d = Duration.of(60 * 60 * 24 * 365, ClockUnit.SECONDS);
d = d.with(Duration.approximateMaxUnitOnly());
System.out.println(d); // P1Y
Due to the nature of this kind of normalization, you cannot expect exact results.
A year doesn't have a fixed amount of seconds:
Leap years have an additional day on February 29
Leap seconds are sometimes added
Due to above you have to know how many seconds are in a year. It seems like instead of Instant and Duration you should be using LocalDate and Period (at least when using java.time):
LocalDate d1 = LocalDate.now();
LocalDate d2 = d1.plusYears(1);
Period p = Period.between(d1, d2);
System.out.println(p); // P1Y
Is there a way to get the current time of the day in seconds? Notice I am asking the time of the day, not UTC time.
What I want is a value (in seconds) between the range 0 - 86,400 (12:00AM - 11:59PM). I'm working on an app that works on a daily basis, and when the day ends, the time (in seconds) should restart back at 0 again.
So let's say it's 10:00AM. I should be getting 36,000 seconds, and if my time is 5:00PM, I should be getting 61,200 seconds.
PS: I do not know the time before hand. The program will figure it out by itself using a currentTime() function.
With Java 8, you could create a Duration instance.
For example :
LocalDateTime date = LocalDateTime.now();
long seconds = Duration.between(date.withSecond(0).withMinute(0).withHour(0), date).getSeconds();
Or more simply you could convert the LocalDateTime to a LocalTime instance and then apply the toSecondOfDay() method :
LocalDateTime date = LocalDateTime.now();
int seconds = date.toLocalTime().toSecondOfDay();
From the java.time.LocalTime javadoc :
public int toSecondOfDay()
Extracts the time as seconds of day, from 0 to 24 * 60 * 60 - 1.
Use a java.time.LocalTime and a java.time.temporal.ChronoField:
// 10:00 AM
LocalTime d = LocalTime.of(10, 0);
System.out.println(d.get(ChronoField.SECOND_OF_DAY)); // 36000
// 05:00 PM
d = LocalTime.of(17, 0);
System.out.println(d.get(ChronoField.SECOND_OF_DAY)); // 61200
// 23:59:59
d = LocalTime.of(23, 59, 59);
System.out.println(d.get(ChronoField.SECOND_OF_DAY)); // 86399
// midnight
d = LocalTime.of(0, 0);
System.out.println(d.get(ChronoField.SECOND_OF_DAY)); // 0
This prints:
36000
61200
86399
0
Notes:
That's just examples. If you want to get the value from the current time, just use LocalTime.now() (or LocalTime.now(ZoneId.of("timezone-name")) as pointed by #Ole V.V.'s answer).
As a timezone-name, always use IANA timezones names (always in the format Continent/City, like America/Sao_Paulo or Europe/Berlin).
Avoid using the 3-letter abbreviations (like CST or PST) because they are ambiguous and not standard. You can get a list of available timezones (and choose the one that fits best your system) by calling ZoneId.getAvailableZoneIds().
You can also call d.toSecondOfDay() if you want (it's equivalent, as get(ChronoField) internally calls toSecondOfDay).
I suggest:
int secondsOfDay = LocalTime.now(ZoneId.of("Europe/Rome")).toSecondOfDay();
Points to note:
Use an explicit time zone to remind the reader and yourself that the choice of time zone matters and that you have made a conscious choice. Either ZoneId.systemDefault(), or even better is if it would make sense in your situation to give a named zone like for example ZoneId.of("Europe/Rome").
The snippet converts 10:00 AM to 36,000 no matter when the day began; because of summer time and other anomalies it may not have begun at 0:00 midnight, and there may be a gap or overlap early in the morning. To get the true number of seconds since the day began, you will need some calculation involving LocalDate.now(yourTimeZone).atStartOfDay(yourTimeZone).
You can just convert the seconds minutes hour fields into seconds and add them up
Calendar c = new GregorianCalendar();
int totalSecs = c.get(Calendar.SECOND) + 60 * c.get(Calendar.MINUTE) + 3600 * c.get(Calendar.HOUR_OF_DAY);
You could use the SimpleDateFormat to extract the hours minutes and seconds. It works on Java 7 and Java 6 and Java 8, and it adapts to your local time and timezone:
String timeNowHMS[] = new SimpleDateFormat("HH:mm:ss", Locale.ENGLISH)
.format(System.currentTimeMillis())
.split(":");
int secondsPassedInTheDay =
Integer.parseInt(timeNowHMS[0]) * 60 * 60
+ Integer.parseInt(timeNowHMS[1]) * 60
+ Integer.parseInt(timeNowHMS[2]);
I'm trying to convert a no of months into milliseconds
For example:
6 months = X milliseconds
There's no fixed answer to that, because it depends on which months those are - and indeed which year it is. Also potentially which time zone you're in, if you want to take account of that. (I'm assuming you mean the Gregorian calendar, by the way - different calendar systems have different month lengths.)
You could get some sort of "reasonable approximation" by assuming 365.25 days in a year, and saying that 6 months is half of that, then find out that many days in milliseconds. But it would only be an approximation.
For "how many milliseconds does it take to get from date/time X to 6 months later" you'd use an API (even Calendar would work for this particular case, although I'd recommend Joda Time or java.time in Java 8):
Set your start date/time, in the appropriate calendar and time zone
Fetch the "milliseconds since the Unix epoch" (which is easy enough to retrieve in any API) and remember it
Add 6 months
Fetch the "milliseconds since the Unix epoch" again, and subtract the earlier value from it
If you know exactly from when to when those 6 months reach, you can use a variety of ways to calculate the duration, using java.util.Calendar, JodaTime, or the JDK1.8 time API.
But if you don't have particular dates in mind, you can take an average duration for your month.
No API in the world can change that fact.
For example, the JDK1.8 time API uses this for the duration of a month in seconds: (from java.time.temporal.ChronoUnit)
MONTHS("Months", Duration.ofSeconds(31556952L / 12)),
31,556,952 is the number of a seconds in a year, based on a year that lasts 365.2425 days.
You can use the same number directly and get the same result as with the time API:
long months = 6;
long seconds = months * 31556952L / 12;
long milliseconds = seconds * 1000;
Result:
15,778,476,000
Calendar today = Calendar.getInstance();
Calendar sixMonthsAhead = Calendar.getInstance();
sixMonthsAhead.add(Calendar.MONTH, 6);
long differenceInMilis = sixMonthsAhead.getTimeInMillis() - today.getTimeInMillis();
You could also use...
sixMonthsAhead.add(Calendar.DATE, 180);
// or 183 days because 365 / 2 is approximately 183.
instead of...
sixMonthsAhead.add(Calendar.MONTH, 6);
for a more accurate result. But like Jon has mentioned, it will always vary depending on what day of the year it is.
The answer by Jon Skeet is correct.
Joda-Time
Assuming you could specify a pair of beginning and ending points on a time line, here is some example code using the Joda-Time 2.3 library.
This code grabs the current moment, adjusts to first of the month, and adjusts to first moment of that day. Then it adds 6 months. Joda-Time is smart about adding the months, taking into account leap year and various lengths of months. This span of 6 months is then represented as an Interval instance. From that we calculate the number of milliseconds. Note that count of milliseconds needs to be a long (64-bit) rather than an int (32-bit) we Java programmers more commonly use. Lastly, for fun, we see what this span of time looks like when formatted in the ISO 8601 standard’s "Duration" format.
DateTimeZone dateTimeZone = DateTimeZone.forID( "Europe/Paris" ); // Better to specify a time zone than rely on JVM’s default.
DateTime start = new DateTime( dateTimeZone ).withDayOfMonth( 1 ).withTimeAtStartOfDay();
DateTime stop = start.plusMonths( 6 );
Interval interval = new Interval( start, stop );
long milliseconds = interval.toDurationMillis(); // A long, not an int.
Period period = interval.toPeriod(); // For fun… ISO 8601 standard's Duration format.
Dump to console…
System.out.println("start: " + start );
System.out.println("stop: " + stop );
System.out.println("interval: " + interval );
System.out.println("milliseconds: " + milliseconds );
System.out.println("period: " + period );
When run…
start: 2014-04-01T00:00:00.000+02:00
stop: 2014-10-01T00:00:00.000+02:00
interval: 2014-04-01T00:00:00.000+02:00/2014-10-01T00:00:00.000+02:00
milliseconds: 15811200000
period: P6M
This question already has answers here:
Java Date rounding
(11 answers)
Closed 6 years ago.
I am looking for a way to convert the datatype DATE [JAVA]
to a quarter of an hour format, so that
2010-08-15 12:05:15 will be 2010-08-15 12:00:00
Are there any ready to go methods in JAVA already?
How would you do this?
Any hints/suggestions?
Use a Calendar object, then you can and manipulate the indvidual fields
int min = cal.get (Calendar.MINUTE);
int val = min / 15; // or what ever logic you have.
Up to release version 7, Java comes with a terrible date and time API. Many developers therefore choose to use Joda time instead. It is a very common third-party dependency in many projects.
Using Joda time, you can do the following:
Date toQuaterOfHour(Date date) {
LocalDateTime ldt = new LocalDateTime(date.getTime());
int quater = ldt.getMinuteOfHour() / 15;
return ldt.withMinuteOfHour(quater * 15).toDate();
}
Java 8 comes with a date and time API that is similar to that of Joda time.
First of all, joda-time is battle tested well known solution for working with date/times in Java, so if you can push it into your project, do it (or at least try).
Second, I can help you with that, but please put here fully qualified name of object you are using. Date in java.util is mostly deprecated, so I would suggest looking on GregorianCalendar object (included in JDK) for date/time manipulation.
You may use simple arithmetic like this:
long millis = 15 * 60 * 1000;
long now = System.currentTimeMillis();
long rest = now % millis;
long quarter = now + (rest == 0 ? 0 : rest >= millis / 2 ? millis - rest : -rest);
System.out.println("Original: " + new Date(now));
System.out.println("Quarter: " + new Date(quarter));
Use the class SimpleDateFormat and choose the output format of your choice.
Chasing some subtle, annoying bugs in a block of code.
This code is given an instance of Calendar which was created at the start of some event. We need to figure out if this event is an hour old.
I know of several ways to do this:
using JodaTime and calculating a Duration
comparing the given Calendar to a new Calendar created for one hour ago
comparing the given Calendar.getTime to a Date created for one hour ago
Each of these methods has its own quirks and seems to have code smells. Is there a simple, concise way to express "happened between now and one hour ago" in Java?
When I unit test this I would check:
45 minutes ago (true)
61 minutes ago (false)
0 minutes ago (true)
-1 minutes ago (error or true?)
You can create a new Calendar instance (with current date/time) and compare it with the given one:
public boolean isWithinHour(Calendar given)
{
long oldTime = given.getTimeInMillis();
long newTime = Calendar.getInstance().getTimeInMillis();
long diff = newTime - oldTime;
return (diff <= 3600 * 1000); // 3600 seconds in millis
}
As a personal preference I'd choose Joda-Time, but I think the implementation is not important. What is important is being clear on the purpose and create a method that you can use.
First you'd better define what means happened one hour ago.
Does it mean exactly a hour ago?
Does it mean within a hour ago?
Does it mean between 45 minutes ago and 1 hour and 15 minutes ago?
After that you choose one of the methods that you mentioned. and you write your own method with a descriptive name that should read naturally in your code.
Probably not very different from the methods you listed, but I don't see how or why it smells:
if (calendar.getTimeInMillis() + (60L * 60L * 1000L)) <= System.currentTimeMillis()) {
// created more than one hour ago
}
The method I would use is to compare against a timestamp 1 hour in the past:
return cal.getTimeInMillis() < (System.currentTimeMillis() - 1000L * 60L * 60L);