Date format takes lots of time in for loop - java

I am traversing an arraylist and want to format all the timestamps i get from response but i observed that it takes around 3 seconds to convert 12600 records using DateFormat method and if i use SimpleDateFormat it takes 2 seconds.Strange!!
But I want to decrease this conversion time.
ArrayList<String> timestampsList = new ArrayList<String>();
Calendar cal = Calendar.getInstance();
for(int i=0;i< arraylist.size();i++) {
cal.setTimeInMillis(arraylist.getTimeStamp());
timestampsList.add(DateFormat.format("kk:mm", cal).toString());
}
Any help will be appreciated!! Thanks

I don't know the static method DateFormat.format(...) - is this an android specific class you are using?
I would assume however that the implementation creates a new format object for the pattern you specify and uses it to format the given calendar.
You could try creating the format object before the loop, see SimpleDateFormat, and then use it inside the loop.
int size = arraylist.size();
String[] timestampsList = new String[size];
java.text.DateFormat format = SimpleDateFormat("kk:mm");
for(int i = 0; i < size; i++) {
Date date = arraylist.get(i).??? ;
timestampsList[i] = format.format(date);
}
Note that the format object you created should not be shared between threads so do not store in a static field.
Also note that Calendar calculations might also be computation intensive, it could be that this is also slowing things down, but if you use SimpleDateFormat directly you can just use raw dates.
You might want also to set the timezone on your format object.

Issue was in DateFormat method.Finally, i used Joda-Time library to convert my date which took 612 ms only..Awesome improvement.
// this one took 612 ms to convert 12600 records
Joda-Time library 2.3 version
private static final DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern("kk:mm");
private static DateTime dateTime = new DateTime();
public String getFormattedLabel(long timeStamp) {
dateTime = dateTime.withMillis(timeStamp);
return dateTime.toString(dateTimeFormatter);
}
and used it like -:
ArrayList<String> timestampsList = new ArrayList<String>();
Calendar cal = Calendar.getInstance();
for(int i=0;i< arraylist.size();
timestampsList.add(getFormattedLabel(arraylist.getTimeStamp());
}

Related

convert time variable to hh:mm format in java

I'm a beginner in java and I with my code below I can generate a random time in "hh:mm:ss" format . I have no idea how to tweak my code to display time in "hh:mm" format as I am not familiar with the
Date and Time java libraries . I have checked posts here like converting time from hh:mm:ss to hh:mm in java but it does not help here .
import java.util.Random;
import java.sql.Time;
final Random random = new Random();
final int millisInDay = 24*60*60*1000;
Time time = new Time((long)random.nextInt(millisInDay));
I have also tried :
// creates random time in hh:mm format for 0-12 hours but I want the full 24 hour timeline
public static String createRandomTime() {
DateFormat format = new SimpleDateFormat("h.mm aa");
String timeString = format.format(new Date()).toString();
return timeString;
}
I would appreciate your help .
You could write a method that creates proper random hours and random minutes, then construct a java.time.LocalTime of them and return a desired String representation.
Here's an example:
public static String createRandomTime() {
// create valid (in range) random int values for hours and minutes
int randomHours = ThreadLocalRandom.current().nextInt(0, 23);
int randomMinutes = ThreadLocalRandom.current().nextInt(0, 59);
// then create a LocalTime from them and return its String representation
return LocalTime.of(randomHours, randomMinutes).format(
// using a desired pattern
DateTimeFormatter.ofPattern("HH:mm")
);
}
Executing that method ten times in a main like this
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
System.out.println(createRandomTime());
}
}
will produce an output like (not necessarily equal to)
08:16
07:54
17:15
19:41
14:24
12:00
12:33
11:00
09:11
02:33
Please note that the int values and corresponding LocalTime created from them will not change if you just want another format. You can easily switch the pattern to another one (maybe make the pattern String a parameter of the method). E.g. you could make it "hh:mm a" for Strings like 10:23 AM.
Since you're using the SimpleDateFormat, I'd suggest taking a look to its documentation
In there, you can see that h is for hour in AM/PM format. Since you want the 24h format, you'll need either H or k, depending if you want it to be 0-23 or 1-24
You can try with the following code,
public void testDateFormat() {
String format = "HH:mm"; //24 hours format
//hh:mm aa for 12 hours format
DateFormat dateFormat = new SimpleDateFormat(format);
String date = dateFormat.format(new Date());
System.out.println(date);
}
There is a fantastic Javadoc is available to explain the details of various options. Please refer the Javadoc as well https://docs.oracle.com/javase/10/docs/api/java/text/SimpleDateFormat.html

Generating all days between 2 given dates in Java [duplicate]

This question already has answers here:
how to get a list of dates between two dates in java
(23 answers)
Closed 6 years ago.
I'm trying to get an array of Dates, while my input is a 'from'/'to' structure.
So my input is:
String date1 = "2014-01-01";
String date2 = "2014-05-01";
My output should be an Arraylist with all dates between date1 and date2.
I've already looked for this, but I could only find questions about the difference between 2 dates:
SimpleDateFormat myFormat = new SimpleDateFormat("dd MM yyyy");
String inputString1 = "23 01 1997";
String inputString2 = "27 04 1997";
try {
Date date1 = myFormat.parse(inputString1);
Date date2 = myFormat.parse(inputString2);
long diff = date2.getTime() - date1.getTime();
System.out.println ("Days: " + TimeUnit.DAYS.convert(diff,TimeUnit.MILLISECONDS));
} catch (ParseException e) {
e.printStackTrace();
}
Any hints or suggestions? All other questions are for iOS or SQL.
Take a look at JodaTime: http://joda-time.sourceforge.net/apidocs/org/joda/time/DateTime.html
DateTime dateTime1 = new DateTime(date1);
DateTime dateTime2 = new DateTime(date2);
List<Date> allDates = new ArrayList();
while( dateTime1.before(dateTime2) ){
allDates.add( dateTime1.toDate() );
dateTime1 = dateTime1.plusDays(1);
}
Below is the code to get array of dates between the two string date.
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
public class DateFormatExample {
public static void main(String[] args) {
// TODO Auto-generated method stub
SimpleDateFormat myFormat = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
String date1 = "2014-01-01";
String date2 = "2014-05-01";
try {
Date d1 = myFormat.parse(date1);
Date d2 = myFormat.parse(date2);
List<Date> allDates = new ArrayList<Date>();
List<String> allDatesString = new ArrayList<String>();
while( d1.before(d2) ){
d1 = addDays(d1, 1);
allDates.add(d1);
allDatesString.add(formatter.format(d1));
}
System.out.println(allDates);
System.out.println(allDatesString);
} catch (ParseException e) {
e.printStackTrace();
}
}
private static Date addDays(Date d1, int i) {
GregorianCalendar cal = new GregorianCalendar();
cal.setTime(d1);
cal.add(Calendar.DATE, 1);
return cal.getTime();
}
}
If you don't want to use third party libraries you can use Calendar:
Check here a working demo.
public static void main(String[] args) throws Exception {
SimpleDateFormat myFormat = new SimpleDateFormat("dd MM yyyy");
String inputString1 = "23 01 1997";
String inputString2 = "27 04 1997";
ArrayList<Date> dates = new ArrayList<Date>();
try {
Date date1 = myFormat.parse(inputString1);
Calendar c1 = DateToCalendar(date1);
Date date2 = myFormat.parse(inputString2);
Calendar c2 = DateToCalendar(date2);
while (!areEqualDate(c1, c2)) {
dates.add(c1.getTime());
System.out.println (c1.getTime());
c1.add(Calendar.DAY_OF_YEAR, 1);
}
} catch (ParseException e) {
e.printStackTrace();
}
// ArrayList<Date> dates >> contain all dates between both given days.
}
private static boolean areEqualDate(Calendar c1, Calendar c2) {
if (c1.get(Calendar.YEAR) != c2.get(Calendar.YEAR)) return false;
if (c1.get(Calendar.MONTH) != c2.get(Calendar.MONTH)) return false;
if (c1.get(Calendar.DAY_OF_YEAR) != c2.get(Calendar.DAY_OF_YEAR)) return false;
return true;
}
public static Calendar DateToCalendar(Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
return cal;
}
I like JodaTime, but this can also be done without 3rd party libraries by using java.util.Calendar. Given a Calendar object, one can use its add method to increase certain fields of the date while honoring the calendar rules (like adding 1 day to the 31st of January gets you to the 1st of February, not to the 32nd of January).
First get the dates into one Calendar object each, in the correct chronological order so adding is going in the right direction later:
Calendar cStart = Calendar.getInstance(),
cStop = Calendar.getInstance();
if (date1.before(date2)) {
cStart.setTime(date1);
cStop.setTime(date2);
} else {
cStart.setTime(date2);
cStop.setTime(date1);
date1 and date2 are the parsed Date objects from your question, for simplicity's sake.
Next, loop over an "add 1 to day-of-year" instruction until this gets you beyond the stop date:
do {
System.out.println(pretty(cStart));
cStart.add(Calendar.DAY_OF_YEAR, 1);
} while (cStart.before(cStop));
And lastly print the stop date
System.out.println(pretty(cStop));
pretty() is just some mini method sending the calendar through a SDF, like the one you used for parsing the Strings in the first place.
This solution will print the date range, including the start and stop dates, and might need some tweaking around the edge cases (like date1==date2). Can be easily adapted to exclude the start and stop dates. Printing can be swapped for aggregation of course. To get a Date object from the calendar, use the getTime() method (returns a snapshot, not a live reference).
The documentation for the relevant (Gregorian)Calendar can be found here.
In case you are using Guava, there is a very elegant solution to this problem.
Guava has two neat classes, such as Range and ContiguousSet, which implement exactly what you need: first one operates on ranges of values, and second one - is able to convert a range to a set of discrete values.
Example of usage of both (together with JodaTime):
LocalDate start = LocalDate.parse("2015-01-01");
LocalDate end = LocalDate.parse("2019-02-01");
Range<LocalDate> range = Range.closed(start, end); //Creates a "closed" range, that is both dates are inclusive. There are also options like "openClosed", "closedOpen" and "open"
final Set<LocalDate> daySet = ContiguousSet.create(range, LocalDateDomain.INSTANCE); //Create a "virtual" set of days in given the range. "virtual" part means that if you create a set of 10 thousand years, it will not eat your memory at all
for (LocalDate day : daySet) {
//...operation...
}
Personally, I really prefer this way, as it eliminates some problems with understanding closed/open ranges, and makes code much easier to read and understand, while making no impact on performance. Also, it works with any kinds of dates, any libraries (you can swap YodaTime to Java8 Dates or even Java7- Date-based implementation).
Moreover, it allows you to do some neat operations on ranges like intersections, unions, spanning of ranges, incredibly fast "contains" and so on.
Only downsides are:
Dependence on Guava.
Need to create a special "DiscreteDomain" class, which Guava uses to understand where one date ends and other begins.
Example of LocalDateDomain implementation which operates as a bridge between Guava and JodaTime:
public class LocalDateDomain extends DiscreteDomain<LocalDate> {
public static final LocalDateDomain INSTANCE = new LocalDateDomain();
#Override
public LocalDate next(LocalDate value) {
return value.plusDays(1);
}
#Override
public LocalDate previous(LocalDate value) {
return value.minusDays(1);
}
#Override
public long distance(LocalDate start, LocalDate end) {
return Days.daysBetween(start, end).getDays();
}
}
I already know that OP isn't using Java 8 but here's the current solution - Java has been revamped and the new java.time API does every conceivable job in that regard:
//change these values :
LocalDate ld1 = LocalDate.ofEpochDay(0);
LocalDate ld2 = LocalDate.now();
//do NOT change these:
final LocalDate begin = ld1.isBefore(ld2) ? ld1 : ld2;
final LocalDate end = ld2.isAfter(ld1) ? ld2 : ld1;
for (int i = 0; i < begin.until(end, ChronoUnit.DAYS); i++) {
final LocalDate curDate = begin.plusDays(i);
System.out.println("current date : " + curDate);
}
This will output every valid day between the two dates whereas most of the other solutions will also give you invalid ones; heres the thing: temporal calculations need to be done on timezone-independent data - the output on the other hand may very well be timezone and/or chronology -dependent.
Thats why there are packages like java.time.format - simply calculate your time/date values and format them for your chosen region ... thats how its done correctly.
If you need to convert temporal input there are also useful functions in the time-API, i recommend doing a thorough tutorial on the subject, a few good introductions may be this and especially that :
There are two basic ways to represent time. One way represents time in
human terms, referred to as human time, such as year, month, day,
hour, minute and second. The other way, machine time, measures time
continuously along a timeline from an origin, called the epoch, in
nanosecond resolution. The Date-Time package provides a rich array of
classes for representing date and time. Some classes in the Date-Time
API are intended to represent machine time, and others are more suited
to representing human time.

Trying to find the difference in days with JodaTime

Simply, I'm storing an 'initial date' data as a String variable in a text file e.g. 02-02-2015, and I just need to know if 3 days has passed from that initial date. I've been recommended to use JodaTime but I kept on recieving errors with it which I'm presuming is because I'm comparing String and Int variables.
Is this possible, if so how? Thanks in advance?
EDIT: Apologies I didn't post the code.
public void startDelay() {
DateTime dt = new DateTime();
DateTimeFormatter fmt = DateTimeFormat.forPattern("dd-MM-yyyy");
delayPin = fmt.print(dt);
}
public int delayEnded() {
DateTime dt = new DateTime();
DateTimeFormatter fmt = DateTimeFormat.forPattern("dd-MM-yyyy");
String today = fmt.print(dt);
delayProgress = Days.daysBetween(new DateTime(delayPin), new DateTime(today)).getDays();
return delayProgress;
}
delayPin is being stored in the text file. I repeated the method to get todays date within the second delayEnded method.
Something like this?
String storedDateString = "02-02-2015";
DateTimeFormatter format =
new DateTimeFormatterBuilder().appendPattern("MM-dd-yyyy").toFormatter();
Boolean isThreeDaysPassed =
LocalDate.now().minusDays(3).isAfter(LocalDate.parse(storedDateString, format));

Java time Error converting data

I have a little problem with the translation of this data 19/12/2005
17:30:45 to mileseconds. I don't know why, I am getting a wrong translation to Jun 28 17:30:45 CEST 1995 Time :804353445798
The code I used is this :
private static long ConvertTimeToTimeStamp(String time) {
Integer[] data = new Integer[6];
String [] tokens = time.split(" ");
System.out.println(tokens[0]);
System.out.println(tokens[1]);
String[] d_m_y = tokens[0].split("/");
String[] hh_mm_ss = tokens[1].split(":");
for (int i = 0; i < d_m_y.length; i++) {
data[i]=Integer.parseInt(d_m_y[i]);
// System.out.println(d_m_y[i]);
}
for (int i = 0; i < hh_mm_ss.length; i++) {
data[i+3]=Integer.parseInt(hh_mm_ss[i]);
// System.out.println(hh_mm_ss[i]);
}
//Calendar calendar = Calendar.getInstance();
GregorianCalendar calendar = new GregorianCalendar();
calendar.set(data[0]+1970, data[1], data[2], data[3],data[4],data[5]);
System.out.println(calendar.getTime().toString());
return calendar.getTimeInMillis();
}
You should not parse the date manually - use a date format instead:
String s = "19/12/2005 17:30:45";
Date d = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss").parse(s);
Treat this object from the outset as a date. That will be much more reliable.
Use SimpleDateFormat.parse() to parse your string into a date/time. Otherwise you're reduced to string parsing/splitting/recombining etc with no bounds-checking, type-checking etc. Your solution is stringly-typed, not strongly-typed.
I've referenced the standard Java libraries, but Joda-Time is a better bet for doing date work in Java and I would advise adopting this for a more intuitive and safer API.
Forget about it. Use a SimpleDataFormat object with pattern dd/MM/yyyy HH:mm:ss to parse() the String into a date object.
try...
private static long ConvertTimeToTimeStamp(String time) {
//19/12/2005 17:30:45
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss");
java.util.Date d = sdf.parse(time);
return d.getTime();
}
You are mixing the order of year, month and day. The set method is expecting them in the following order: year, month, day and you are providing them as day + 1970, month, year.
Having said that, you might actually be much more happy with a library like joda-time.

How can I parse a period of date into a String[ ] day by day in Java?

For example,the input parameters are 2011-01-01 and 2012-01-01,
and I want to parse this period day by day like 2011-01-01~2011-01-02, 2011-01-02~2011-01-03...
Finally,store them in a array of String?
Thanks in advance.
For parsing the date from a string, I recommend using SimpleDateFormat.
That way you will obtain a Date object. Use the Date object to create a GregorianCalendar.
Then, you can use GregorianCalendar's add method to increase it one day at a time until you reach your end date.
Here's a code example:
String dateString1 = "2011-01-01";
String dateString2 = "2012-01-01";
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
List<String> dates = new ArrayList<String>();
Date startDate = dateFormat.parse(dateString1);
Date endDate = dateFormat.parse(dateString2);
GregorianCalendar calendar = new GregorianCalendar();
calendar.setTime(startDate);
while (calendar.getTime().before(endDate)) {
dates.add(dateFormat.format(calendar.getTime()));
calendar.add(Calendar.DAY_OF_MONTH, 1);
}
This puts your dates in a list. You can convert it to an array like this:
String[] datesArray = dates.toArray(new String[0]);
You should really work on your accept rate. but the basic method would go like this :
psuedo-code:
Date first = "2011-01-01";
Date last = "2012-01-01";
Calendar cal = new Calendar(first);
List<Date> dates = ...;
while (first.before(last)) {
cal.addDays(1);
dates.add(cal);
}
This should be really easy to implement using GregorianCalendar, or you can check out joda-time which would make this a whole lot of easy...

Categories

Resources