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
Related
I'm using this library I just discovered which is supposedly less heavier than Joda time for android and I said what the heck, let's use it. But now I'm struggling to find any good examples on the web about how to use it, besides these two methods I have:
// ZonedDateTime contains timezone information at the end
// For example, 2011-12-03T10:15:30+01:00[Europe/Paris]
public static ZonedDateTime getDate(String dateString) {
return ZonedDateTime.parse(dateString).withZoneSameInstant(ZoneId.of("UTC"));
}
public static String formatDate(String format, String dateString) {
return DateTimeFormatter.ofPattern(format).format(getDate(dateString));
}
So how can I get the difference between two dates with this library?
There are several options depending on what you require from the difference you obtain.
It’s easiest to find the difference measured in some time unit. Use ChronoUnit.between. For example:
ZonedDateTime zdt1 = getDate("2011-12-03T10:15:30+01:00[Europe/Paris]");
ZonedDateTime zdt2 = getDate("2017-11-23T23:43:45-05:00[America/New_York]");
long diffYears = ChronoUnit.YEARS.between(zdt1, zdt2);
System.out.println("Difference is " + diffYears + " years");
long diffMilliseconds = ChronoUnit.MILLIS.between(zdt1, zdt2);
System.out.println("Difference is " + diffMilliseconds + " ms");
This prints:
Difference is 5 years
Difference is 188594895000 ms
I am using your getDate method, so the format required is that of ZonedDateTime (modified from ISO 8601), for example 2011-12-03T10:15:30+01:00[Europe/Paris]. Seconds and fraction of second are optional, as is time zone ID in square brackets.
BTW you don’t need to convert to UTC before finding the difference. You will get the same result even if you leave out that conversion.
You may also get the difference in years, months and days. The Period class can give you this, but it cannot handle time of day, so convert to LocalDate first:
Period diff = Period.between(zdt1.toLocalDate(), zdt2.toLocalDate());
System.out.println("Difference is " + diff);
Difference is P5Y11M21D
The output means a period of 5 years 11 months 21 days. The syntax may feel a little strange at first, but is straightforward. It is defined by the ISO 8601 standard. In this case the time zone matters since it is never the same date in all time zones.
To get the difference in hours, minutes and seconds use the Duration class (I am introducing a new time since using Duration for nearly 6 years would be too atypical (though possible)).
ZonedDateTime zdt3 = getDate("2017-11-24T18:45:00+01:00[Europe/Copenhagen]");
Duration diff = Duration.between(zdt2, zdt3);
System.out.println("Difference is " + diff);
Difference is PT13H1M15S
A period of 13 hours 1 minute 15 seconds. The T that you already know from 2011-12-03T10:15:30+01:00[Europe/Paris] here too separates the date part from the time part so you know that in this case 1M means 1 minute, not 1 month.
I am developing a weekly event, but I need to get the milliseconds (unix timestamp) by next Saturday. How can I do that?
1 create a calendar
Calendar calNow = Calendar.getInstance();
2 create another calendar, set it to midnight and move day by day until you hit Saturday
Calendar calNextSat = Calendar.getInstance();
calNextSat.set(Calendar.HOUR, 0);
calNextSat.set(Calendar.MINUTE, 0);
calNextSat.set(Calendar.SECOND, 0);
while(calNextSat.get(Calendar.DAY_OF_WEEK) != Calendar.SATURDAY){
calNextSat.add(Calendar.DATE, 1);
}
System.out.println(calNextSat.getTimeInMillis() - calNow.getTimeInMillis());
handle the scenario if it is already Saturday you would get <=0 result
I am developing a weekly event
Using milliseconds for this kind of date-time tracking will probably lead you astray. For example, because of Daylight Saving Time (DST) and other anomalies, a day is not always 24-hours long and therefore a week is not always ( ( 1000L * 60 * 60 * 24 ) * 7 ) milliseconds long.
Joda-Time or java.time
I suggest learning how to use a sophisticated date-time library. In Java that means either:
Joda-Time
java.time (built into Java 8, inspired by Joda-Time).
Time Zone
The time zone is crucial in determining the day and day-of-week. Use proper time zone names, never the 3 or 4 letter codes.
Example Code To Get Next Day-Of-Week
Here is example code using Joda-Time 2.7.
Get the time zone you desire/expect. If working in UTC, use the constant DateTimeZone.UTC.
DateTimeZone zone = DateTimeZone.forID( "America/Montreal" );
Get the date-time value you need. Here I am using the current moment.
DateTime dateTime = DateTime.now( zone );
Specify the future day-of-week you want. Note that Joda-Time uses the sensible # 1 for first day of week, rather than zero-based counting found in java.util.Calendar. First day of week is Monday, per international norms and standards (not Sunday as is common in United States).
int dayOfWeek = DateTimeConstants.SATURDAY;
The withDayOfWeek command may go back in time. So we use a ternary operator (?:) to make sure we go forwards in time by adding a week as needed.
DateTime future = ( dateTime.getDayOfWeek() < dayOfWeek )
? dateTime.withDayOfWeek( dayOfWeek )
: dateTime.plusWeeks( 1 ).withDayOfWeek( dayOfWeek );
You may want to adjust the time-of-day to the first moment of the day to emphasize the focus on the day rather than a particular moment within the day.
future = future.withTimeAtStartOfDay(); // Adjust time-of-day to first moment of the day to stress the focus on the entire day rather than a specific moment within the day. Or use `LocalDate` class.
Dump to console.
System.out.println( "Next day # " + dayOfWeek + " after " + dateTime + " is " + future );
When run.
Next day # 6 after 2015-04-18T16:03:36.146-04:00 is 2015-04-25T00:00:00.000-04:00
Until Then
The code above gives us the desired future point in time (next Saturday).
If all you really want is the number of milliseconds between now and then, subtract between each one’s internal count-from-epoch in milliseconds. Note the use of 64-bit long rather than 32-bit int when tracking times as milliseconds.
long elapsedMilliseconds = ( future.getMillis() - dateTime.getMillis() );
Note that if you are doing this work in java.time rather Joda-Time, be aware that internally java.time uses nanoseconds rather than milliseconds. You can find milliseconds-savvy methods as I recall. Or divide nanoseconds by a million (yes, million not thousand, as microseconds are in between.
You may want to more intelligently represent the span of time between now and then. Joad-Time offers three classes for representing a span of time in various manners:
Interval (a pair of fixed points on the time line)
Period (a number of months, days, hours, and such)
Duration (a number of milliseconds).
Example code, again Joda-Time 2.7.
Interval interval = new Interval( dateTime , future );
Period period = interval.toPeriod();
Dump to console.
System.out.println( "interval: " + interval );
System.out.println( "period: " + period );
When run.
interval: 2015-04-18T16:17:45.109-04:00/2015-04-25T00:00:00.000-04:00
period: P6DT7H42M14.891S
Notice the String representation format used by default for the Period value. That format is standard, part of ISO 8601, called a duration in their terminology. That format is PnYnMnDTnHnMnS where the P marks the beginning and the T separates the date portion from the time portion.
Both Joda-Time and java.time use ISO 8601 as their defaults in both parsing and generating string representations of date-time values.
I would use a Calendar to get the current day of the week. And you could subtract it like,
public static int daysUntilSaturday(Date d) {
Calendar cal = Calendar.getInstance();
cal.setTime(d);
return 7 - cal.get(Calendar.DAY_OF_WEEK);
}
Then you can perform simple arithmetic like
/*
* 1000 milliseconds in a second, 60 seconds in a minute, 60 minutes in
* an hour, 24 hours in a day.
*/
final long millisecondsPerDay = 1000L * 60 * 60 * 24;
System.out.println((daysUntilSaturday(new Date()) * millisecondsPerDay)
+ System.currentTimeMillis());
I have two unix time stamps like
currentTimestamp=1213083655;
previousTimestamp=1213083715;
How do I calculate the number of minutes between these two timestamps. Or in other words difference in minutes between both these timestamps.
Currently what I am doing is
(previousTimestamp-currentTimestamp)%60
which is the right away to go because timestamps are time in seconds and doing this will return minutes . But only problem is that when the difference is multiple of 60 then the remainder is 0 and therefore the calculation gives a result of 0 minutes which is wrong. Like in the case of above numbers difference is 60 so result is 0. So what's the best way to do this?
Regards
Ahmar
Use division instead of modulo.
% is the modulo command. You're not getting the number of minutes. You're getting the remaining number of seconds after calculating whole minutes.
/ is the division command. This is what you are looking for.
(previousTimestamp-currentTimestamp)/60
This is the command you want.
You don't want a modulo, but a division. Let's say the difference is 150 seconds. You need to divide it by 60 to find the difference in minutes: 2.5:
double differenceInMinutes = (currentTimestamp - previousTimestamp) / 60d;
You can use JodaTime in your project for date/time operations. To find out the gap between two DateTime in minutes:
DateTime now = DateTime.now();
DateTime dateTime = now.plusMinutes(10);
Minutes minutes = Minutes.minutesBetween(now, dateTime);
System.out.println(minutes.getMinutes());
If you use Maven, you can add JodaTime adding following dependency:
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.3</version>
</dependency>
Why do you use a %?
% gives you module,that not what you're looking for.
/ is what you have to use. A simple division.
The answer by Erhan Bagdemir is correct.
Here is his idea using the Joda-Time library, but adapted to literally solve the problem with values given by the question.
Using Joda-Time 2.3 and Java 7.
// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.
// import org.joda.time.*;
// We do not need time zones if our only goal is to count minutes. But realistically we are probably doing other work as well.
// Better to specify a time zone explicitly rather than rely on default.
// Time Zone list… http://joda-time.sourceforge.net/timezones.html (not quite up-to-date, read page for details)
DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" );
// Convert Unix time (seconds since epoch of 1970) to Joda-Time DateTime count of milliseconds since same epoch.
// Note the use of the 'long' type rather than the usual 'int', a common error when working with millisecond counts since epoch.
// Notice the hard-coded "L" on the numbers.
long start = ( 1213083655L * 1000L );
long stop = ( 1213083715 * 1000L );
DateTime dateTimeStart = new DateTime( start, timeZone );
DateTime dateTimeStop = new DateTime( stop, timeZone );
int minutesElapsed = Minutes.minutesBetween( dateTimeStart, dateTimeStop ).getMinutes();
Dump to console…
System.out.println( "dateTimeStart: " + dateTimeStart );
System.out.println( "dateTimeStop: " + dateTimeStop );
System.out.println( "minutesElapsed: " + minutesElapsed );
When run…
dateTimeStart: 2008-06-10T09:40:55.000+02:00
dateTimeStop: 2008-06-10T09:41:55.000+02:00
minutesElapsed: 1
I would like to know exactly how many months and days(possibly years) some older date is from today. Is there a method to do that?
I know how to get the difference of the months, I know how to get the difference in days. But I am unable to get the months and the days.
Ex:
old = '2013-03-04'
now = '2013-04-17'
so the result im looking for is something like 1 month(s) and 13* day(s)
*maybe its 12 im not every sure.
This can be done by using Period in JodaTime.
For example,
LocalDate old = new LocalDate(2013, 3, 4);
LocalDate now = new LocalDate(2013, 4, 17);
Period p = new Period(old, now, PeriodType.yearMonthDay());
To get the months, use p.getMonths(), to get the days p.getDays().
The result of the example is 1 month, 13 days.
Yes, see the documentation of intervals:
Intervals
An interval in Joda-Time represents an interval of time from one
instant to another instant. Both instants are fully specified instants
in the datetime continuum, complete with time zone.
Intervals are implemented as half-open, which is to say that the start
instant is inclusive but the end instant is exclusive. The end is
always greater than or equal to the start. Both end-points are
restricted to having the same chronology and the same time zone.
Two implementations are provided, Interval and MutableInterval, both
are specializations of ReadableInterval.
How can I add two dates in Java?
Example: The sum of "2010-01-14 19:16:17" "0000-10-03 01:10:05"
would result in "2010-11-17 20:26:22".
I know how to do it using Calendar and adding field by field.
Is any other way to sum them all (year/month/day/hour/minute/second) at once?
If you are using the Date object, you can just do:
Date d1 = ...
Date d2 = ...
long sum = d1.getTime() + d2.getTime();
Date sumDate = new Date(sum);
The code uses the .getTime() method that returns the number of milliseconds since the epoch.
Needless to say the Date class has a lot of problems and should be avoided when possible.
Do you want to sum other types instead?
Update: for Calendar, I would do the following (based on javadocs):
Calendar c1 = ...
Calendar c2 = ...
long sum = c1.getTimeInMillis() + c2.getTimeInMillis();
Calendar sumCalendar = (Calendar)c1.clone();
sumCalendar.setTimeInMillis(sum);
UPDATED: As Steve stated, this works if the Date you presented here assumes that the second date is with respect to the Java epoch. If you do want to start with year "0", then you need to account for that (by subtracting your epoch time).
Don't sum the time in millis of the two dates!
Date d1 = new Date();
Date d2 = new Date();
Date dTotal = new Date(d1.getTime() + d2.getTime());
System.out.println(dTotal); // Incorrect! Misses about 1970 years.
Just clone the Calendar and add the datetime parts one by one.
Calendar c1 = Calendar.getInstance();
Calendar c2 = Calendar.getInstance();
Calendar cTotal = (Calendar) c1.clone();
cTotal.add(Calendar.YEAR, c2.get(Calendar.YEAR));
cTotal.add(Calendar.MONTH, c2.get(Calendar.MONTH) + 1); // Months are zero-based!
cTotal.add(Calendar.DATE, c2.get(Calendar.DATE));
cTotal.add(Calendar.HOUR_OF_DAY, c2.get(Calendar.HOUR_OF_DAY));
cTotal.add(Calendar.MINUTE, c2.get(Calendar.MINUTE));
cTotal.add(Calendar.SECOND, c2.get(Calendar.SECOND));
cTotal.add(Calendar.MILLISECOND, c2.get(Calendar.MILLISECOND));
System.out.println(cTotal.getTime()); // Correct!
Needless to say, JodaTime is smarter and cleaner with this.
As always, I would recommend the Java 8 date/time APIs or Joda for date/time work, since they are much more powerful and intuitive.
You can add durations and periods to a DateTime object trivially. You can add minutes/seconds/months equally easily.
However, you can't add two dates directly, since that doesn't really make sense. This is a powerful illustration of why Joda is a help - it stops you doing stuff that you really shouldn't be doing.
tl;dr
LocalDateTime later =
LocalDateTime
.parse (
"2010-01-14 19:16:17"
.replace ( " " , "T" )
)
.plus( Period.parse ( "P10M3D" ) )
.plus( Duration.parse ( "PT1H10M5S" ) )
;
ISO 8601
The representation of a span-of-time using the same format as a moment is creating confusion. A span is not at all the same as a moment.
Instead of using YYYY-MM-DD HH-MM-SS format for a span of time, I suggest using the standard ISO 8601 format of PnYnMnDTnHnMnS. In this format, the P marks the beginning (for "Period" presumably) and the T separates the years-month-days portion from the hours-minutes-seconds portion.
Example values:
PT1H30M → One and a half hours.
P3Y6M4DT12H30M5S → Three years, six months, four days, twelve hours, thirty minutes, and five seconds.
P10M3DT1H10M5S → Your Question’s duration of 0000-10-03 01:10:05.
java.time
The Question and the other Answers use troublesome old date-time classes now outmoded by the java.time framework built into Java 8 and later. See Oracle Tutorial. Much of the java.time functionality has been back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP.
The java.time classes use ISO 8601 formats by default when parsing and generating Strings that represent date-time values.
The Question does not provide any time zone info, so here we use the LocalDateTime class. If we know an offset-from-UTC we would use the OffsetDateTime class, and if even better we knew a time zone, we would use the ZonedDateTime class.
Spans of time in java.time are divided amongst a pair of classes. Years-months-days are represented by the Period class, and hours-minutes-seconds are handled by the Duration class.
Combining these times, we can indeed perform date-time math. Here we add a span of time to an starting date-time to get a resulting date-time. And we do so in very few lines of code. The result is indeed that expected by the Question.
We convert the input strings to canonical ISO 8601 format by replacing the SPACE in the middle with a T.
LocalDateTime ldt = LocalDateTime.parse ( "2010-01-14 19:16:17".replace ( " " , "T" ) );
//"0000-10-03 01:10:05"
Period period = Period.parse ( "P10M3D" );
Duration duration = Duration.parse ( "PT1H10M5S" );
LocalDateTime result = ldt.plus ( period ).plus ( duration );
Compare to the result expected in the Question.
LocalDateTime expectation = LocalDateTime.parse ( "2010-11-17 20:26:22".replace ( " " , "T" ) );
Boolean isSame = result.equals ( expectation );
Dump to console.
System.out.println ( "ldt: " + ldt + " + period: " + period + " + duration: " + duration + " is result: " + result + " compared to expectation: " + expectation + " is the same: " + isSame );
ldt: 2010-01-14T19:16:17 + period: P10M3D + duration: PT1H10M5S is result: 2010-11-17T20:26:22 compared to expectation: 2010-11-17T20:26:22 is the same: true
You want to do getTimeInMillis() on both those Calendars so you'll have two honest-to-goodness long values you can add up. You can then take the sum and stash it in a new Calendar using that Calendar's setTimeInMillis() method.
Whether you want to add two Calendars as shown above or two Dates as shown in notnoop's answer is up to you, of course. The effect is similar, it just depends on what you want to do with the result. A Date is mostly just good for storing and/or converting to a String for printing out or displaying, whereas a Calendar will let you fiddle with the individual time values should you so choose.
As others have mentioned, you're committing some conceptual no-no's in using a Date or Calendar, which are meant to store "real" dates and times, e.g. ones in the 20th or 21st century, as intervals, i.e. time spans. The classes in the standard Java library don't give you really useful tools to handle this, which is why the Joda classes were developed. All the cool kids in date/time processing use those; but on the other hand that involves downloading and managing a 3rd party library.
notnoop answer is definitely correct. However, if you are going to do lots of processing of dates, times and intervals, I suggest that you look at class DateUtils in apache commons lang and at joda-time library.
JDK7 will come with better support for some of the features that joda-time provides. Just saying ... it might be a consideration if your app makes heavy usage of this stuff.
You need to define your EPOCH. The Java epoch (like Unix) is 1 Jan 1970 GMT/UTC. I assume you think you're adding ten months, 3 days and some odd hours from 1 Jan 0000 but you have a epoch offset until 1970. The maths may not necessarily work.
Use Calendar or Joda (as mentioned). If you just simply want to add a number of seconds and days (&c) then feel free to add said # of milliseconds to your first date object.
Use calendar class add method to add two dates in java.
Calendar calendar=Calendar.getInstance();
calendar.add(Calendar.Date,23);
calendar.add(Calendar.Month,13);
calendar.add(Calendar.Year,15);
By using add method in Calendar class we can add day,month,year to the existing date.
click here for complete program.
I am occasionally guilty of this practice too, storing time interval in a date object and using getTime() as suggested by notnoop.
It works. Contrary to certain opinion, it certainly works. I just ignore that the interval could be representative of an unintended date. It is a quick and dirty way for me to add an interval, say, [6 years, 6 months, 6 days, 6 hours, 6 minutes, 6 seconds] to a date.