I have this code:
SimpleDateFormat sDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
I know that this code return hour, minute, second in the time.
How i can get also the millisecond and microsecond??
You won't have microseconds, because a Date stores the number of milliseconds since Jan. 1 1970. For the milliseconds, use S, as documented in the javadoc.
The only way to get micro-seconds is to parse the string yourself. Note: Date should be used to store micro-seconds, but you can use a long. (which you can also use for milli-seconds or nano-seconds)
private static final String YEARS_TO_MINUTES = "yyyy-MM-dd HH:mm";
private static final SimpleDateFormat YEARS_TO_MINUTES_SDF = new SimpleDateFormat(YEARS_TO_MINUTES);
public static long parseMicroSeconds(String text) throws ParseException {
long timeMS;
synchronized (YEARS_TO_MINUTES_SDF) {
timeMS = YEARS_TO_MINUTES_SDF.parse(text.substring(0, YEARS_TO_MINUTES.length())).getTime();
}
long microSecs = 0;
if (text.length() > YEARS_TO_MINUTES.length() + 1) {
double secs = Double.parseDouble(text.substring(YEARS_TO_MINUTES.length() + 1));
microSecs = (long) (secs * 1e6 + 0.5);
}
return timeMS * 1000 + microSecs;
}
public static String formatMicroSeconds(long timeMicroSeconds) {
String dateTime;
synchronized (YEARS_TO_MINUTES_SDF) {
dateTime = YEARS_TO_MINUTES_SDF.format(new Date(timeMicroSeconds / 1000));
}
long secs = timeMicroSeconds % 60000000;
return dateTime + String.format(":%09.6f", secs / 1e6);
}
public static void main(String... args) throws ParseException {
String dateTime = "2011-01-17 19:27:59.999650";
long timeUS = parseMicroSeconds(dateTime);
for (int i = 0; i < 5; i++)
System.out.println(formatMicroSeconds(timeUS += 175));
}
prints
2011-01-17 19:27:59.999825
2011-01-17 19:28:00.000000
2011-01-17 19:28:00.000175
2011-01-17 19:28:00.000350
2011-01-17 19:28:00.000525
You can do similarly if you need nano-timings.
The best you can do is:
SimpleDateFormat sDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
You can only show the millisecond: :SS.
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
public class MyClass
{
public static void main(String args[]) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss:SSSSS");
for(int i=0; i<=5;i++) {
System.out.println("Class 1 : " + ZonedDateTime.now().format(formatter));
}
}
}
Example output:
Class 1 : 19:25:19:77336
Class 1 : 19:25:19:77483
Class 1 : 19:25:19:77487
Class 1 : 19:25:19:77490
Class 1 : 19:25:19:77493
Class 1 : 19:25:19:77496
Check the Java-doc of SimpleDateFormat, it tells :
Millisecond : S
Microseconds are not available.
This example gets millisecond. Microseconds isn't available.
Date someDate = sDate.parse(dateString);
Calendar c = Calendar.setTime(someDate);
int millisecond = c.get(Calendar.MILLISECOND);
Generally the milliseconds are given with capital s and in your case it will be yyyy-MM-dd HH:mm:ss:SSS. For more info refer to Customizing formats
Related
I'm trying to generate a random date of birth for people in my database using a Java program. How would I do this?
import java.util.GregorianCalendar;
public class RandomDateOfBirth {
public static void main(String[] args) {
GregorianCalendar gc = new GregorianCalendar();
int year = randBetween(1900, 2010);
gc.set(gc.YEAR, year);
int dayOfYear = randBetween(1, gc.getActualMaximum(gc.DAY_OF_YEAR));
gc.set(gc.DAY_OF_YEAR, dayOfYear);
System.out.println(gc.get(gc.YEAR) + "-" + (gc.get(gc.MONTH) + 1) + "-" + gc.get(gc.DAY_OF_MONTH));
}
public static int randBetween(int start, int end) {
return start + (int)Math.round(Math.random() * (end - start));
}
}
java.util.Date has a constructor that accepts milliseconds since The Epoch, and java.util.Random has a method that can give you a random number of milliseconds. You'll want to set a range for the random value depending on the range of DOBs that you want, but those should do it.
Very roughly:
Random rnd;
Date dt;
long ms;
// Get a new random instance, seeded from the clock
rnd = new Random();
// Get an Epoch value roughly between 1940 and 2010
// -946771200000L = January 1, 1940
// Add up to 70 years to it (using modulus on the next long)
ms = -946771200000L + (Math.abs(rnd.nextLong()) % (70L * 365 * 24 * 60 * 60 * 1000));
// Construct a date
dt = new Date(ms);
Snippet for a Java 8 based solution:
Random random = new Random();
int minDay = (int) LocalDate.of(1900, 1, 1).toEpochDay();
int maxDay = (int) LocalDate.of(2015, 1, 1).toEpochDay();
long randomDay = minDay + random.nextInt(maxDay - minDay);
LocalDate randomBirthDate = LocalDate.ofEpochDay(randomDay);
System.out.println(randomBirthDate);
Note: This generates a random date between 1Jan1900 (inclusive) and 1Jan2015 (exclusive).
Note: It is based on epoch days, i.e. days relative to 1Jan1970 (EPOCH) - positive meaning after EPOCH, negative meaning before EPOCH
You can also create a small utility class:
public class RandomDate {
private final LocalDate minDate;
private final LocalDate maxDate;
private final Random random;
public RandomDate(LocalDate minDate, LocalDate maxDate) {
this.minDate = minDate;
this.maxDate = maxDate;
this.random = new Random();
}
public LocalDate nextDate() {
int minDay = (int) minDate.toEpochDay();
int maxDay = (int) maxDate.toEpochDay();
long randomDay = minDay + random.nextInt(maxDay - minDay);
return LocalDate.ofEpochDay(randomDay);
}
#Override
public String toString() {
return "RandomDate{" +
"maxDate=" + maxDate +
", minDate=" + minDate +
'}';
}
}
and use it like this:
RandomDate rd = new RandomDate(LocalDate.of(1900, 1, 1), LocalDate.of(2010, 1, 1));
System.out.println(rd.nextDate());
System.out.println(rd.nextDate()); // birthdays ad infinitum
You need to define a random date, right?
A simple way of doing that is to generate a new Date object, using a long (time in milliseconds since 1st January, 1970) and substract a random long:
new Date(Math.abs(System.currentTimeMillis() - RandomUtils.nextLong()));
(RandomUtils is taken from Apache Commons Lang).
Of course, this is far to be a real random date (for example you will not get date before 1970), but I think it will be enough for your needs.
Otherwise, you can create your own date by using Calendar class:
int year = // generate a year between 1900 and 2010;
int dayOfYear = // generate a number between 1 and 365 (or 366 if you need to handle leap year);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, randomYear);
calendar.set(Calendar.DAY_OF_YEAR, dayOfYear);
Date randomDoB = calendar.getTime();
For Java8 -> Assumming the data of birth must be before current day:
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.Period;
import java.time.temporal.ChronoUnit;
import java.util.Random;
public class RandomDate {
public static LocalDate randomBirthday() {
return LocalDate.now().minus(Period.ofDays((new Random().nextInt(365 * 70))));
}
public static void main(String[] args) {
System.out.println("randomDate: " + randomBirthday());
}
}
If you don't mind adding a new library to your code you can use MockNeat (disclaimer: I am one of the authors).
MockNeat mock = MockNeat.threadLocal();
// Generates a random date between [1970-1-1, NOW)
LocalDate localDate = mock.localDates().val();
System.out.println(localDate);
// Generates a random date in the past
// but beore 1987-1-30
LocalDate min = LocalDate.of(1987, 1, 30);
LocalDate past = mock.localDates().past(min).val();
System.out.println(past);
LocalDate max = LocalDate.of(2020, 1, 1);
LocalDate future = mock.localDates().future(max).val();
System.out.println(future);
// Generates a random date between 1989-1-1 and 1993-1-1
LocalDate start = LocalDate.of(1989, 1, 1);
LocalDate stop = LocalDate.of(1993, 1, 1);
LocalDate between = mock.localDates().between(start, stop).val();
System.out.println(between);
Generating random Date of Births:
import java.util.Calendar;
public class Main {
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
System.out.println(randomDOB());
}
}
public static String randomDOB() {
int yyyy = random(1900, 2013);
int mm = random(1, 12);
int dd = 0; // will set it later depending on year and month
switch(mm) {
case 2:
if (isLeapYear(yyyy)) {
dd = random(1, 29);
} else {
dd = random(1, 28);
}
break;
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
dd = random(1, 31);
break;
default:
dd = random(1, 30);
break;
}
String year = Integer.toString(yyyy);
String month = Integer.toString(mm);
String day = Integer.toString(dd);
if (mm < 10) {
month = "0" + mm;
}
if (dd < 10) {
day = "0" + dd;
}
return day + '/' + month + '/' + year;
}
public static int random(int lowerBound, int upperBound) {
return (lowerBound + (int) Math.round(Math.random()
* (upperBound - lowerBound)));
}
public static boolean isLeapYear(int year) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, year);
int noOfDays = calendar.getActualMaximum(Calendar.DAY_OF_YEAR);
if (noOfDays > 365) {
return true;
}
return false;
}
}
You can checkout randomizer for random data generation.This library helps to create random data from given Model class.Checkout below example code.
public class Person {
#DateValue( from = "01 Jan 1990",to = "31 Dec 2002" , customFormat = "dd MMM yyyy")
String dateOfBirth;
}
//Generate random 100 Person(Model Class) object
Generator<Person> generator = new Generator<>(Person.class);
List<Person> persons = generator.generate(100);
As there are many built in data generator is accessible using annotation,You also can build custom data generator.I suggest you to go through documentation provided on library page.
Look this method:
public static Date dateRandom(int initialYear, int lastYear) {
if (initialYear > lastYear) {
int year = lastYear;
lastYear = initialYear;
initialYear = year;
}
Calendar cInitialYear = Calendar.getInstance();
cInitialYear.set(Calendar.YEAR, 2015);
long offset = cInitialYear.getTimeInMillis();
Calendar cLastYear = Calendar.getInstance();
cLastYear.set(Calendar.YEAR, 2016);
long end = cLastYear.getTimeInMillis();
long diff = end - offset + 1;
Timestamp timestamp = new Timestamp(offset + (long) (Math.random() * diff));
return new Date(timestamp.getTime());
}
I think this will do the trick:
public static void main(String[] args) {
Date now = new Date();
long sixMonthsAgo = (now.getTime() - 15552000000l);
long today = now.getTime();
for(int i=0; i<10; i++) {
long ms = ThreadLocalRandom.current().nextLong(sixMonthsAgo, today);
Date date = new Date(ms);
System.out.println(date.toString());
}
}
If you don't mind a 3rd party library, the Utils library has a RandomDateUtils that generates random java.util.Dates and all the dates, times, instants, and durations from Java 8's date and time API
LocalDate birthDate = RandomDateUtils.randomPastLocalDate();
LocalDate today = LocalDate.now();
LocalDate under18YearsOld = RandomDateUtils.randomLocalDate(today.minus(18, YEARS), today);
LocalDate over18YearsOld = RandomDateUtils.randomLocalDateBefore(today.minus(18, YEARS));
It is in the Maven Central Repository at:
<dependency>
<groupId>com.github.rkumsher</groupId>
<artifactId>utils</artifactId>
<version>1.3</version>
</dependency>
simplest method:
public static LocalDate randomDateOfBirth() {
final int maxAge = 100 * 12 * 31;
return LocalDate.now().minusDays(new Random().nextInt(maxAge));
}
Using the original answer and adapting it to the new java.time.* api and adding ways to generate n random dates -- the function will return a List.
// RandomBirthday.java
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class RandomBirthday {
public static List<String> getRandomBirthday(int groupSize, int minYear, int maxYear) {
/** Given a group size, this method will return `n` random birthday
* between 1922-2022 where `n=groupSize`.
*
* #param groupSize the number of random birthday to return
* #param minYear the min year [lower bound]
* #param maxYear the max year [upper bound]
* #return a list of random birthday with format YYYY-MM-DD
*/
ArrayList<String> birthdays = new ArrayList<>();
DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd");
for (int i = 0; i < groupSize; i++) {
LocalDate baseDate = LocalDate.now();
LocalDate baseYear = baseDate.withYear(ThreadLocalRandom.current().nextInt(minYear, maxYear));
int dayOfYear = ThreadLocalRandom.current().nextInt(1, baseYear.lengthOfYear());
LocalDate baseRandBirthday = baseYear.withDayOfYear(dayOfYear);
LocalDate randDate = LocalDate.of(
baseRandBirthday.getYear(),
baseRandBirthday.getMonth(),
baseRandBirthday.getDayOfMonth()
);
String formattedDate = dateFormat.format(randDate);
birthdays.add(formattedDate);
}
return birthdays;
}
public static void main(String[] args) {
// main method
List<String> bDay = getRandomBirthday(40, 1960, 2022);
System.out.println(bDay);
}
}
I am studying Scala and ended up Googling Java solutions for choosing a random date between range. I found this post super helpful and this is my final solution. Hope it can help future Scala and Java programmers.
import java.sql.Timestamp
def date_rand(ts_start_str:String = "2012-01-01 00:00:00", ts_end_str:String = "2015-01-01 00:00:00"): String = {
val ts_start = Timestamp.valueOf(ts_start_str).getTime()
val ts_end = Timestamp.valueOf(ts_end_str).getTime()
val diff = ts_end - ts_start
println(diff)
val ts_rand = new Timestamp(ts_start + (Random.nextFloat() * diff).toLong)
return ts_rand.toString
} //> date_rand: (ts_start_str: String, ts_end_str: String)String
println(date_rand()) //> 94694400000
//| 2012-10-28 18:21:13.216
println(date_rand("2001-01-01 00:00:00", "2001-01-01 00:00:00"))
//> 0
//| 2001-01-01 00:00:00.0
println(date_rand("2001-01-01 00:00:00", "2010-01-01 00:00:00"))
//> 283996800000
//| 2008-02-16 23:15:48.864 //> 2013-12-21 08:32:16.384
int num = 0;
char[] a={'a','b','c','d','e','f'};
String error = null;
try {
num = Integer.parseInt(request.getParameter("num"));
Random r = new Random();
long currentDate = new Date().getTime();
ArrayList<Student> list = new ArrayList<>();
for (int i = 0; i < num; i++) {
String name = "";
for (int j = 0; j < 6; j++) {
name += a[r.nextInt(5)];
}
list.add(new Student(i + 1, name, r.nextBoolean(), new Date(Math.abs(r.nextLong() % currentDate))));
}
request.setAttribute("list", list);
request.setAttribute("num", num);
request.getRequestDispatcher("student.jsp").forward(request, response);
} catch (NumberFormatException e) {
error = "Please enter interger number";
request.setAttribute("error", error);
request.getRequestDispatcher("student.jsp").forward(request, response);
}
public static void main(String[] args) throws ParseException {
String myTime = "08:00";
int diffHour = 2;
SimpleDateFormat df = new SimpleDateFormat("HH:mm");
Date d = df.parse(myTime);
Calendar cal = Calendar.getInstance();
cal.setTime(d);
for (int i=0; i<=diffHour; i++) {
cal.add(Calendar.HOUR, i);
String newTime = df.format(cal.getTime());
System.out.println(newTime);
}
}
The output is:
08:00
09:00
11:00
I want it to be:
08:00
09:00
10:00
because in the different two hours only until 10:00 if we started with 08:00.
Why did the output jump from 10:00 to 11:00?
The answer by Draken is correct. You are adding i where you should be adding a number one 1.
java.time
You are also using old troublesome classes now outmoded by the java.time classes.
LocalTime
The LocalTime class represents a time-of-day-only value without date and without time zone.
LocalTime start = LocalTime.parse( "08:00" );
int hours = 2;
LocalTime time = start;
for ( int i = 0 ; i <= hours ; i++ ) {
String output = time.toString();
// Set up next loop.
time = time.plusHours( 1 );
}
cal.add(Calendar.HOUR, 1);
You're adding i, which will increase by one on each loop, so for the first it will add zero, then one, and then two. Instead, since you want to add by a concrete number, try instead to add just 1.
Though that does mean you would need to start at 07:00, the other choice is to put some logic in, but that depends on what you are expecting. Something like this could work:
for (int i=0; i<=diffHour; i++) {
if (i <= 1) {
cal.add(Calendar.HOUR, i);
} else {
cal.add(Calendar.HOUR, 1);
}
String newTime = df.format(cal.getTime());
System.out.println(newTime);
}
Here's a fiddle of it working
Try something like this:
package org.app.temputil;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public class Test {
public static void main(String[] args) throws ParseException {
String myTime = "08:00";
int diffHour = 2;
SimpleDateFormat df = new SimpleDateFormat("HH:mm");
Date d = df.parse(myTime);
Calendar cal = Calendar.getInstance();
cal.setTime(d);
for (int i = 0; i <= diffHour; i++) {
cal.add(Calendar.HOUR, i == 0 ? 0 : 1);
String newTime = df.format(cal.getTime());
System.out.println("i=[" + i + "], time=" + newTime);
}
}
}
Here is the description of your code -
for (int i=0; i<=diffHour; i++) {
cal.add(Calendar.HOUR, i);
String newTime = df.format(cal.getTime());
System.out.println(newTime);
}
Here the loop is running for i = 0, 1, 2.
For i = 0, 0 is added to calendar so that value remains same as it was earlier 8.
For i = 1, 1 is added to calendar so the value becomes 8 (earlier value) + 1 = 9
For i = 2, 2 is added to calendar so the value becomes 9 (earlier value) + 2 = 11.
To make it work,
Remove the line - cal.add(Calendar.HOUR, i);
Add this line -
if (i == 0) {
cal.add(Calendar.HOUR, 0);
} else {
cal.add(Calendar.HOUR, 1);
}
change your loop to this
for (int i=0; i<=diffHour; i++) {
String newTime = df.format(cal.getTime());
System.out.println(newTime);
cal.add(Calendar.HOUR, 1);
}
Let's say I have two datetimes, 30-11-2015 10:00 and 02-12-2015 15:00. I also have two times, 07:00 and 22:00. How could I calculate the amount of time passed between the two date/times that was within the second times? Using Calendar object? It seems simple but its boggling my mind.
Since none of the other answers include runnable code, I can't tell if they solve the problem or not.
To calculate the duration of a time range within a date range, you have to:
Split the date range into multiple date ranges, each spanning no more than one day.
Calculate the time range within each day date range
Taking the example date range from the question. 30-11-2015 10:00 and 02-12-2015 15:00, we generate the following split day date ranges:
30-11-2015 10:00 - 30-11-2015 24:00
01-12-2015 00:00 - 01-12-2015 24:00
02-12-2015 00:00 - 02-12-2015 15:00
Now, we can apply the time range of 7:00 - 22:00 to each of the split day date ranges.
30-11-2015 10:00 - 30-11-2015 24:00 -> 12 hours
01-12-2015 00:00 - 01-12-2015 24:00 -> 15 hours
02-12-2015 00:00 - 02-12-2015 15:00 -> 8 hours
For a total of 35 hours. The actual calculation would probably be in minutes instead of hours.
Edited to add: I created a Time and a TimeRange class to hold the time and a day time range, respectively. I used the java.util.Date, although I had to create my own increment a day method.
I put all of the classes together so I could post this easier. The classes should be put in separate files.
package com.ggl.testing;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class TimeRangeTest {
private static final SimpleDateFormat inputDateFormat = new SimpleDateFormat(
"dd-MM-yyyy");
public static void main(String[] args) {
TimeRangeTest test = new TimeRangeTest();
int minutes = test.calculateTotalMinutes("30-11-2015 10:00",
"02-12-2015 15:00", "07:00", "22:00");
System.out.println(minutes + " minutes, " + (minutes / 60) + " hours");
}
public int calculateTotalMinutes(String startDateTimeString,
String endDateTimeString, String startTimeString,
String endTimeString) {
try {
List<TimeRange> timeRanges = generateTimeRanges(
startDateTimeString, endDateTimeString);
return calculateTimeRange(timeRanges, startTimeString,
endTimeString);
} catch (ParseException e) {
e.printStackTrace();
return 0;
}
}
private List<TimeRange> generateTimeRanges(String startDateTimeString,
String endDateTimeString) throws ParseException {
Date startDate = inputDateFormat.parse(startDateTimeString.substring(0,
10));
Time startTime = new Time(startDateTimeString.substring(11));
Date endDate = inputDateFormat
.parse(endDateTimeString.substring(0, 10));
Time endTime = new Time(endDateTimeString.substring(11));
List<TimeRange> timeRanges = new ArrayList<>();
Date currentDate = new Date(startDate.getTime());
Time currentTime = new Time(startTime);
Time eodTime = new Time("24:00");
while (currentDate.compareTo(endDate) < 0) {
TimeRange timeRange = new TimeRange(currentDate, currentTime,
eodTime);
timeRanges.add(timeRange);
currentTime = new Time("00:00");
currentDate = new Date(currentDate.getTime() + 24L * 60L * 60L
* 1000L);
}
TimeRange timeRange = new TimeRange(currentDate, currentTime, endTime);
timeRanges.add(timeRange);
return timeRanges;
}
private int calculateTimeRange(List<TimeRange> timeRanges,
String startTimeString, String endTimeString) {
int count = 0;
Time startTime = new Time(startTimeString);
Time endTime = new Time(endTimeString);
for (TimeRange timeRange : timeRanges) {
Time sodTime = new Time(timeRange.getStartTime());
Time eodTime = new Time(timeRange.getEndTime());
Time sTime = startTime.max(sodTime);
Time eTime = endTime.min(eodTime);
count += eTime.difference(sTime);
}
return count;
}
public class TimeRange {
private final SimpleDateFormat inputDateFormat = new SimpleDateFormat(
"dd-MM-yyyy");
private final Date date;
private final Time startTime;
private final Time endTime;
public TimeRange(Date date, Time startTime, Time endTime) {
this.date = date;
this.startTime = startTime;
this.endTime = endTime;
}
public Date getDate() {
return date;
}
public Time getStartTime() {
return startTime;
}
public Time getEndTime() {
return endTime;
}
#Override
public String toString() {
return inputDateFormat.format(getDate()) + " "
+ startTime.toString() + " -> " + endTime.toString();
}
}
public class Time {
private final int minutesPastMidnight;
public Time(String timeString) {
int hours = Integer.valueOf(timeString.substring(0, 2));
int minutes = Integer.valueOf(timeString.substring(3, 5));
this.minutesPastMidnight = hours * 60 + minutes;
}
public Time(Time time) {
this.minutesPastMidnight = time.getMinutesPastMidnight();
}
private int getMinutesPastMidnight() {
return minutesPastMidnight;
}
public int difference(Time time) {
return this.getMinutesPastMidnight()
- time.getMinutesPastMidnight();
}
public Time min(Time time) {
return (difference(time) > 0) ? time : this;
}
public Time max(Time time) {
return (difference(time) > 0) ? this : time;
}
#Override
public String toString() {
int hours = minutesPastMidnight / 60;
int minutes = minutesPastMidnight - (hours * 60);
return String.format("%02d:%02d", hours, minutes);
}
}
}
If you use java8, you can use LocalDateTime. Then your code could looks like this:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
LocalDateTime dateTimeStart = LocalDateTime.parse("2015-10-01 10:00", formatter);
LocalDateTime dateTimeEnd = LocalDateTime.parse("2015-10-02 10:00", formatter);
long seconds = Duration.between(dateTimeStart, dateTimeEnd).getSeconds();
Or LocalTime if you have only time. Then it could looks like this:
LocalTime timeStart = LocalTime.parse("07:00");
LocalTime timeEnd = LocalTime.parse("22:00");
long seconds = Duration.between(timeStart, timeEnd).getSeconds();
If you can't use java8, you can get the number of milliseconds since 1970-01-01 00:00:00 to your date using getTime() method and do simple subtraction operation, like this:
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
Date dateStart = simpleDateFormat.parse("2015-10-01 10:00");
Date dateEnd = simpleDateFormat.parse("2015-10-02 10:00");
long milliseconds = dateEnd.getTime() - dateStart.getTime();
long seconds = resultInMillisecond / 1000;
I'm working on a report that calculates a sum of the data in it and some of the data are timestamps, for example:
----------------------
| Activity | Time |
----------------------
| 1 | 11:00:00 |
-----------------------
| 2 | 12:00:00 |
-----------------------
| 3 | 13:00:00 |
-----------------------
| Total | 36:00:00 |
----------------------
I'm trying to sum timestamps as below:
final DateFormat dt = new SimpleDateFormat("HH:mm:ss");
final Calendar c = Calendar.getInstance(TimeZone.getDefault(), Locale.getDefault());
c.setTimeInMillis(0);
for (final String t : timestampsList) {
c.add(Calendar.MILLISECOND, (int) dt.parse(t).getTime());
}
The variable timestampsList is an ArrayList of String's, all respecting the pattern used by the SimpleDateFormat object. The problem with the given code is that I can't generate the value of the sum of the timestamps, by using the same SimpleDateFormat what I get is an hour in the pattern informed in a future date.
I also have seen Joda Time Duration class but I'm not familiar with this lib and I 'don't know if I'm in a correct path that will lead me to the right answer.
Does anyone know how to handle it by using J2SE or Joda Time?
I would just parse these Strings myself, convert them to
seconds or milliseconds and sum them up. See answer 2 below.
ANSWER 1
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
public class Test051 {
public static void main(String[] args) throws Exception {
String pt = "1970-01-01-";
ArrayList<String> timestampsList = new ArrayList<String>();
timestampsList.add("01:00:05");
timestampsList.add("01:00:05");
timestampsList.add("10:00:05");
final DateFormat dt = new SimpleDateFormat("yyyy-MM-dd-HH:mm:ss");
final Calendar sum = Calendar.getInstance();
sum.setTimeInMillis(0);
long tm0 = new SimpleDateFormat("yyyy-MM-dd").parse(pt).getTime();
System.out.println("tm0 = " + tm0);
for (final String t : timestampsList) {
// System.out.println(dt.parse(pt + t).getTime());
Date x = dt.parse(pt + t);
// System.out.println(x.getTime());
sum.add(Calendar.MILLISECOND, (int)x.getTime());
sum.add(Calendar.MILLISECOND, (int)-tm0);
}
long tm = sum.getTime().getTime();
System.out.println("tm = " + tm);
tm = tm / 1000;
long hh = tm / 3600;
tm %= 3600;
long mm = tm / 60;
tm %= 60;
long ss = tm;
System.out.println(format(hh) + ":" + format(mm) + ":" + format(ss));
}
private static String format(long s){
if (s < 10) return "0" + s;
else return "" + s;
}
}
ANSWER 2
import java.util.ArrayList;
public class Test051 {
public static void main(String[] args) throws Exception {
ArrayList<String> timestampsList = new ArrayList<String>();
timestampsList.add("01:00:05");
timestampsList.add("01:00:05");
timestampsList.add("10:00:05");
long tm = 0;
for (String tmp : timestampsList){
String[] arr = tmp.split(":");
tm += Integer.parseInt(arr[2]);
tm += 60 * Integer.parseInt(arr[1]);
tm += 3600 * Integer.parseInt(arr[0]);
}
long hh = tm / 3600;
tm %= 3600;
long mm = tm / 60;
tm %= 60;
long ss = tm;
System.out.println(format(hh) + ":" + format(mm) + ":" + format(ss));
}
private static String format(long s){
if (s < 10) return "0" + s;
else return "" + s;
}
}
ANSWER 3
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
public class Test051 {
public static void main(String[] args) throws Exception {
ArrayList<String> timestampsList = new ArrayList<String>();
timestampsList.add("01:00:00");
timestampsList.add("02:00:00");
timestampsList.add("03:00:00");
timestampsList.add("04:00:00");
timestampsList.add("02:00:00");
timestampsList.add("04:00:00");
Date dt0 = new SimpleDateFormat("yyyy-MM-dd").parse("1970-01-01");
// Check very carefully the output of this one.
System.out.println(dt0.getTime());
final DateFormat dt = new SimpleDateFormat("HH:mm:ss");
final Calendar c = Calendar.getInstance();
c.setTimeInMillis(0);
for (final String t : timestampsList) {
c.add(Calendar.MILLISECOND, (int) dt.parse(t).getTime());
c.add(Calendar.MILLISECOND, (int)-dt0.getTime());
}
// We need to add this back. This is basically the time zone offset.
c.add(Calendar.MILLISECOND, (int)dt0.getTime());
System.out.println(c.getTime().getTime());
System.out.println(c.getTimeInMillis());
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(c.getTime()));
System.out.println(new SimpleDateFormat("HH:mm:ss").format(c.getTime()));
}
}
If you don't wanna use peter petrov solution to parse your String yourself, the way to do it with Calendar and SimpleDateFormat is as follow :
List<String> timestampsList = new ArrayList<String>();
timestampsList.add("11:00:00");
timestampsList.add("12:00:00");
timestampsList.add("13:00:00");
final DateFormat dt = new SimpleDateFormat("HH:mm:ss");
final Calendar c = Calendar.getInstance(TimeZone.getDefault(), Locale.getDefault());
long milliseconds = 0;
c.clear();
long startingMS = c.getTimeInMillis();
for (final String t : timestampsList) {
milliseconds = milliseconds + (dt.parse(t).getTime() - startingMS);
}
System.out.println(milliseconds + " milliseconds");
System.out.println(milliseconds / 1000 + " seconds");
System.out.println(milliseconds / 1000 / 60 + " minutes");
System.out.println(milliseconds / 1000 / 60 / 60 + " hours");
Or use
long startingMS = dt.parse("00:00:00").getTime();
for (final String t : timestampsList) {
milliseconds = milliseconds + (dt.parse(t).getTime() - startingMS);
}
instead, removing the need for the Calendar.
Both result in :
129600000 milliseconds
129600 seconds
2160 minutes
36 hours
Note that you might wanna make the results a double not to miss part of the time.
This is a original code from petrov with some edits made by me. Since it's quite dificult to discuss in comments providing big snippets of code I posted it as an answer so we can discuss petrov's other considerations.
public static void somaTempos(final String[] listaTempos) throws ParseException {
long tm = 0;
final DateFormat dt = new SimpleDateFormat("HH:mm:ss");
final Calendar c = Calendar.getInstance(TimeZone.getDefault(), Locale.getDefault());
for (String tmp : listaTempos) {
c.setTime(dt.parse(tmp));
tm += c.get(Calendar.SECOND) + 60 * c.get(Calendar.MINUTE) + 3600 * c.get(Calendar.HOUR_OF_DAY);
}
final long l = tm % 3600;
System.out.println(SIGRUtil.format(tm / 3600) + ':' + SIGRUtil.format(l / 60) + ':' + SIGRUtil.format(l % 60));
}
private static String format(long s) {
if (s < 10) {
return "0" + s;
}
return String.valueOf(s);
}
UPDATE: An alternative that also solves my problem:
public static String sumTimes(final String[] timestampList) {
long milliseconds = 0;
final DateFormat dt = new SimpleDateFormat("HH:mm:ss");
dt.setLenient(false);
try {
final long timezoneOffset = dt.parse("00:00:00").getTime();
for (final String t: timestampList) {
milliseconds += (dt.parse(t).getTime() - timezoneOffset);
}
} catch (final ParseException e) {
throw new BusinessException(
"One of the timestamps in the timestamp list cannot be applied to the HH:mm:ss pattern.", e);
}
((SimpleDateFormat) dt).applyPattern(":mm:ss");
return new StringBuilder(8).append(milliseconds / 3600000).append(
dt.format(new Date(milliseconds))).toString();
}
Actually, the API gives me for free the minutes and the seconds by only reaplying another pattern in the DateFormat after calculating the sum of the time stamps, without forgetting to consider the timezone offset in this calculation, my real problem was how to calculate the number of hours which really is the less dificult part.
Any suggestions of improvements?
If those data input Strings represent durations in hours:minutes:seconds without any date or time-of-day, then the other answers are working much too hard.
Generally, the old java.util.Date and .Calendar classes are notoriously troublesome and should be avoided. Specifically here, those classes have no notion of a span of time. Instead you should be using either Joda-Time or maybe java.time.
Joda-Time
Joda-Time offers three classes to represent a span of time: Interval, Period, and Duration. The first is tied to points along the timeline of the Universe. The other two are not.
The Period and Duration classes are very close cousins. Period is a tuple with a number of years, months, days, hours, minutes, and seconds. Duration is a number of milliseconds with no concept of fields such as days or seconds.
Joda-Time uses the ISO 8601 standard for its defaults in parsing and generating strings. For period/duration time, this means the PnYnMnDTnHnMnS format. The P means "period" and the T is a separator between date and time portions.
Here is some example code in Joda-Time 2.3. Basically a couple of lines: parsePeriod & durationSum.plus seen below.
Simulate input strings.
List<String> durationStrings = new ArrayList<String>();
durationStrings.add( "11:00:00" ); // Number of hours/minutes/seconds. Not time-of-day.
durationStrings.add( "12:00:00" );
durationStrings.add( "13:00:00" ); // Expect sum of 36 hours = 11 + 12 + 13.
Define a formatter to parse those strings. Joda-Time might have such a formatter built-in, but I could not locate it. So I defined one.
PeriodFormatter formatter = new PeriodFormatterBuilder()
.appendHours()
.appendSeparator( ":" )
.appendMinutes()
.appendSeparator( ":" )
.appendSeconds()
.toFormatter();
Loop the input strings, parsing each one, then adding its duration to the sum.
Duration durationSum = Duration.ZERO; // Initializing to empty amount. Add to this in loop below.
for ( String durationString : durationStrings ) {
Period period = formatter.parsePeriod( durationString );
Duration duration = period.toStandardDuration();
durationSum = durationSum.plus( duration );
System.out.println( "period: " + period );
System.out.println( "duration: " + duration );
}
System.out.println( "durationSum: " + durationSum );
System.out.println( "durationSum as Period: " + durationSum.toPeriod() );
When run…
period: PT11H
duration: PT39600S
period: PT12H
duration: PT43200S
period: PT13H
duration: PT46800S
durationSum: PT129600S
durationSum as Period: PT36H
I am trying to create a custom week counter but am having quite a lot of trouble and feel like I am going about it all wrong. The method should take in a string date that is in yyyy-MM-dd format and return the week number. The week counter started October 1, 2000. The week starts Friday and ends Thursday. The first 2 digits represents the years and the second 2 represent the week. So this week would be 1143 (11 to represent the year and 43 to represent the weeks since Oct 1).
This is what I have gotten so far:
public static String get_week(String date){
try{
Calendar first_dt = Calendar.getInstance();
first_dt.set(1999, 10, 01);
long first_dt_milliseconds = first_dt.getTimeInMillis();
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
Date format_date = (Date)formatter.parse(date);
SimpleDateFormat month = new SimpleDateFormat("MM");
SimpleDateFormat year = new SimpleDateFormat("yyyy");
long drop_dt_milliseconds = format_date.getTime() - first_dt_milliseconds;
long drop_dt_years = drop_dt_milliseconds / (24 * 60 * 60 * 1000) / 365;
Calendar year_ago = Calendar.getInstance();
year_ago.set(Integer.parseInt(year.format(format_date))-1, 10, 01);
long year_ago_milliseconds = year_ago.getTimeInMillis();
long year_ago_diff = format_date.getTime() - year_ago_milliseconds;
year_ago_diff = year_ago_diff / (24 * 60 * 60 * 1000) / 7;
if (month.format(format_date).equals("10") || month.format(format_date).equals("11") || month.format(format_date).equals("12")){
date = drop_dt_years+1+""+year_ago_diff;
}
else{
date = year_ago_diff;
}
}catch(Exception e){
e.printStackTrace();
}
return date;
}
I used Joda-Time because it's less confusing than Java's built-in date and time gear
EDIT - new code, rolled in ChssPly's suggestion and fixed a problem with the weeks between Oct 1 and Jan 1. Also check out X-Zero's suggestion to create a custom Chronology in Joda-Time, might be an interesting approach.
import org.joda.time.DateMidnight;
import org.joda.time.Weeks;
import org.joda.time.Years;
public class Main {
private String getWeek (DateMidnight dt2) {
DateMidnight dt = new DateMidnight(2000,10,1);
// First get the number of elapsed years, ChssPly76's way
int yearz = Years.yearsBetween(dt, dt2).getYears();
/*
* We now need the number of weeks in the current year, which can be
* calculated using the Weeks class.
*/
int yearOffset = 1;
// But if the new date is Oct 1 thru Dec 12 year must remain the same
if (!dt2.isBefore (new DateMidnight(dt2.getYear(),10,1))) {
yearOffset = 0;
}
int weekz = Weeks.weeksBetween(dt.withYear(dt2.getYear()-yearOffset), dt2).getWeeks();
return(yearz + " " + weekz);
}
private void test (DateMidnight testDate) {
System.out.println("For date " + testDate + " years/weeks = " + getWeek(testDate));
}
private void run() {
test (new DateMidnight());
test (new DateMidnight(2010,10,8));
test (new DateMidnight(2010,9,30));
test (new DateMidnight(2000,10,1));
}
public static void main(String[] args) {
new Main().run();
}
}
Which outputs
For date 2011-07-26T00:00:00.000+02:00 years/weeks = 10 42
For date 2010-10-08T00:00:00.000+02:00 years/weeks = 10 1
For date 2010-09-30T00:00:00.000+02:00 years/weeks = 9 52
For date 2000-10-01T00:00:00.000+02:00 years/weeks = 0 0
Probably a slightly more sophisticated return object would be better....