Sorting out the dates in chronological order - java

Friends I am having a String that contains date-record
String date=10-Oct-2012 #12-Oct-2012 #$12-Oct-2012 #12-Oct-2012 #$12-Sept-2012 13:50#12-Oct-2012 13:50#$12-Feb-2012 13:50#12-Oct-2012 13:50#$
List<Date> myList=new ArrayList<Date>() ;
I need to compare the dates 10-Oct-2012,12-OCt-2012,12-Sept-2012,12-Feb-2012 ie every odd date such that I can arrange them in a chronological order.I am confused on this implementation, please provide me with guidance/hint to solve the problem.
In this case the solution after chronological order would be 12-Feb-2012 #12-Oct-2012 #12-Sept-2012 #12-Oct-2012 #$10-Oct-2012 #12-Oct-2012 #$12-Oct-2012 #12-Oct-2012
Friends,to solve the problem I have created a Hashmap where I am planning to save the first date as key and the entire String as value.
String[] tokens=date.split("\\$");
demo[0]=demo[0].replaceAll("-", ".");
if(tokens.length>0)
{
for(int iTmp=tokens.length-1;iTmp>=0;iTmp--)
{
String []demo = tokens[iTmp].split("\\#");
demo[0] = demo[0].replace("Jan", "1")
.replace("Feb", "2").replace("March","3").replace("April","4").replace("May","5").replace("Jun","6").replace("July","7").replace("Aug","8")
.replace("Sept","9").replace("Oct","10").replace("Nov","11").replace("Dec","12");
demo[0]=demo[0]+" 00:05:00";
Date date1 = null;
SimpleDateFormat formatter = new SimpleDateFormat("dd.MM.yy");
try {
date1 = (Date)formatter.parse(demo[0]);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
myList.add(date1);
System.out.println("ADDED DATE IS"+date1);
//System.out.println("KEY VALUE PAIRS "+key+" "+tokens[iTmp]);
}
}
System.out.println("READING LISTs");
for(int iTmp=0;iTmp<myList.size();iTmp++)
{
System.out.println(myList.get(iTmp));
}
Collections.sort(myList);
System.out.println("After Sorting");
for(int iTmp=0;iTmp<myList.size();iTmp++)
{
System.out.println(myList.get(iTmp));
System.out.println();
}

It sounds pretty simple to me:
Parse each value into a more suitable type (Calendar, Date, Joda Time's LocalDate)
Sort in natural order
(Using Joda Time is the preferred option here IMO, as neither Calendar nor Date really represent "just a date"; you'd have to put all values into the same time zone etc.)
I would definitely not recommend trying to compare them as strings. As usual, convert your data into the most appropriate type for the information it's trying to represent as early as possible - and convert it into serializing representations (e.g. for storage, propagation to a web service etc) as late as possible.

Split the string and then
You can use gregorian calender (built in)
or you can use the yoda-time library
i can't say more about the sorting though

If you are developing for Android (there is an Android tag on your question), then you should know about the Time structures and methods in the Android SDK.
If possible, try to use a string representation of your date/time stamp that itself can be sorted naturally, like the RFC 3339 format (which Android supports with built-in methods). This will let you work more easily with string timestamps, and also give you a simple way to convert to a canonical or integer-type format if desired.

Related

Finding index in an ArrayList

I have a CSV file that i stored as an arraylist in Java. Here's the code i ran
public class StockData {
private ArrayList<StockRecord> records;
public StockData() {
records = new ArrayList<StockRecord>();
}
//reads the file from the folder
public void loadPriceData(String filepath) {
try {
Scanner scanner = new Scanner(new FileReader(filepath));
String line;
StockRecord record;
scanner.nextLine();
while (scanner.hasNextLine()) {
line = scanner.nextLine();
String[] results= line.split(",");
double open = Double.parseDouble( results[1]);
double high = Double.parseDouble( results[2]);
double low = Double.parseDouble( results[3]);
double close = Double.parseDouble( results[4]);
double volume = Double.parseDouble( results[5]);
double adjClose = Double.parseDouble( results[6]);
//create the record
record = new StockRecord(results[0], open, high, low, close, volume, adjClose);
records.add(record);
}
scanner.close();
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
}
}
}
The code works correctly however, i am having trouble with the next part of the project.
Data Example
Date Open High Low Close Volume Adj Close
6/10/2011 128.85 128.93 127.26 127.6 238629400 126.97
6/13/2011 127.89 128.24 127.05 127.7 207599800 127.07
6/14/2011 128.87 129.77 128.82 129.32 160570400 128.68
6/15/2011 128.24 129.3 126.68 127.02 300958000 126.39
6/16/2011 127.06 127.97 126.32 127.3 308032800 126.67
I'm trying to print out the AdjClose price for a date range. say between 6/13/2011 and 06/15/2016. It seems like i would need to find the index of the date first and then print the price record.
How can i do this? I'm not sure where to start. Do i first need to save the date in the its own list/array and use that to find the index?
Thanks
You would need to iterate through the list of StockRecord and compare each record's date to your specified range. If it falls in the range you would print it. This can be optimized if your list is sorted.
To compare first date is preferable to use a data type date
If your array could scouring records and objects of type StockRecord comparing your date field you want to evaluate
for (StockRecord reg : records) {
if(reg.date.after(historyDate) && reg.date.before(futureDate)) {
System.out.println(reg.toString()); // print object
}
}
Your Question is really a duplicate of many others in Stack Overflow.
LocalDate
Your example code does not actually show the date as part of your StockRecord class. But it should be a member of type LocalDate. Search Stack Overflow for countless posts on how to parse your input string into a LocalDate.
Comparator
Define a Comparator for your class, to extract the LocalDate for comparisons. The LocalDate class itself implements the compareTo method, as well as isBefore, isAfter, and isEqual.
Benefit of sorting
If you will be doing this query often, then it makes sense to sort the StockRecord objects into a List. Then you can be smart about searching, again discussed on many other posts in Stack Overflow.
SortedMap
You could organize the StockRecord objects into a SortedMap, mapping the LocalDate to a Collection of the StockRecord objects sharing that particular date. Using a SortedMap rather than a mere Map lets you do smarter searches for a date range, as mentioned above. Again, many posts on Stack Overflow about maps.
Apache Commons CSV
By the way, Apache Commons CSV project makes easy work of reading and parsing a CSV data file.
BigDecimal
Do not use double or Double for currency amounts, or for any fractional number where accuracy matters. Those types are floating-point types, built for speed but trading away accuracy. You will be introducing extraneous extra digits into the end of the decimal fraction.
Instead use BigDecimal. Yet again, many posts on Stack Overflow on this class.
Integers
Do not use a fractional number like Double for an integer number such as your Volume field. Doing so wastes memory, and creates confusion to anyone reading your code.
Use a 32-bit integer or Integer if your maximum value is two billion or less (2^31-1 = 2,147,483,647), otherwise a 64-bit long or Long.

Java Apache POI -- Creating an iterator to find a date

I am attempting to find the cell reference for a specific date in an Excel file. The Excel is set up so that the "Date" header is in A1, and dates are included across the same row in B1, C1, etc.
I attempted to create an iterator to go through these dates and compare them to an input date.
I omitted some code below for conciseness.
public static void main(String[] args) throws IOException, ParseException {
SimpleDateFormat formatter ;
formatter = new SimpleDateFormat("MM/dd/yyyy");
Date date = formatter.parse(args[0]);
// ............
// iterator to find date
int dateRef = 0; //logs column of date
Date tempDate = null;
// while loop to check the date contents of each cell
while (dateRef < 1000) { // random number inserted
dateRef++;
tempDate = cell.getDateCellValue();
if (date == tempDate) {
break; //beaks if contents are equal
}
cell = results.getRow(0).getCell(dateRef); // else continue and iterate one cell
}
}
When I run this, the iterator keeps going right up to column 1000. I checked this with print statements. Even though the cell is landing on the correct date, it does not recognize the input date and the cell date value as the same, and therefore does not break.
I know this may not be the most efficient way of doing things, so if you have more suggestions, let me know about them. Thank you!
You should not use the == operator in this case. I would try with equals or compareTo in your case in order to find the proper date.
See the Question: What is the difference between == vs equals() in Java?

Android: Incorrect Date when Converting from Seconds

I'm parsing some date data from an XML string into a hierarchy of model objects. The dates are in a 10-digit seconds format. I use the method below to convert those seconds into Date objects
public static Date getDateFromSecondsString(String seconds){
try{
long millis = Long.parseLong(seconds) * 1000;
Date date = new Date(millis);
return date;
}
catch(Exception ex){
ex.printStackTrace();
}
return null;
}
Here's the problem...
When I step through the parsing code at run-time (the code snippet for that is shown below), the date conversion method is returning the expected date.
Element startDateElt = eventElt.getChild("start_date");
if(startDateElt != null){
startDateElt.setEndTextElementListener(new EndTextElementListener() {
#Override
public void end(String body) {
currEvent.startDate = DateTimeUtil.getDateFromSecondsString(body);
}
});
}
However, once I have finished populating my model objects with the parsed data, the dates are wrong. Here are some examples:
Seconds: 1369206000, should be: 2013-05-22, unfortunately is: 2013-05-03
Seconds: 1369292400, should be: 2013-05-23, unfortunately is: 2013-05-04
Seconds: 1369551600, should be: 2013-05-26, unfortunately is: 2013-04-30
Seconds: 1369638000, should be: 2013-05-27, unfortunately is: 2013-05-01
Seconds: 1369724400, should be: 2013-05-28, unfortunately is: 2013-05-02
I have looked through my code to make sure nothing is modifying the dates between the time that the XML is parsed and the time that I display the dates. I know that the Date objects in Java/Android are a little messed up, but would they behave like this?
Any suggestions or insights would be greatly appreciated.
Turns out, the problem was that I was using Date.toDay() in some places where I should have been using Date.toDate() instead. Grrr! I dislike Java's Date implementation.
Thanks to all of you that gave your two cents, and let this be a warning for anyone who may be confusing toDay() with toDate().

Most efficient way of checking if Date object and Calendar object are in the same month

I am working on a project that will run many thousands of comparisons between dates to see if they are in the same month, and I am wondering what the most efficient way of doing it would be.
This isn't exactly what my code looks like, but here's the gist:
List<Date> dates = getABunchOfDates();
Calendar month = Calendar.getInstance();
for(int i = 0; i < numMonths; i++)
{
for(Date date : dates)
{
if(sameMonth(month, date)
.. doSomething
}
month.add(Calendar.MONTH, -1);
}
Creating a new Calendar object for every date seems like a pretty hefty overhead when this comparison will happen thousands of times, soI kind of want to cheat a bit and use the deprecated method Date.getMonth() and Date.getYear()
public static boolean sameMonth(Calendar month, Date date)
{
return month.get(Calendar.YEAR) == date.getYear() && month.get(Calendar.MONTH) == date.getMonth();
}
I'm pretty close to just using this method, since it seems to be the fastest, but is there a faster way? And is this a foolish way, since the Date methods are deprecated? Note: This project will always run with Java 7
I can't comment on whether to use the deprecated methods, but if you choose not to there's no need to instantiate a new Calendar for every Date you check. Just use one other Calendar and call setTime(date) before the check (or one Calendar for every thread if you parallelize it).
As a side note, I do have to agree with ChristopheD's comment that this is something worthy of a database.
I think you can define a static DateFormat to extract the month and year from Date and use both objects as date only.
public static DateFormat formatter= new SimpleDateForm("MMyyyy");
public static boolean sameMonth(Date date1, Date date2)
{
return formatter.format(date1).equals(formatter.format(date2));
}

Grouping objects by date: am I an idiot?

I have a list of objects called Activity:
class Activity {
public Date activityDate;
public double amount;
}
I want to iterate through List, group them by date and return a new list . Here's what I currently do:
private List<Activity> groupToList(List<Activity> activityList) {
SimpleDateFormatter sdf = new SimpleDateFormatter("YYYY-MM-DD");
Map<String,Activity> groupMap = new HashMap<String,Activity>();
for (Activity a in activityList) {
String key = sdf.format(a.getActivityDate());
Activity group = groupMap.get(key);
if (group == null) {
group = new Activity();
groupMap.add(key, group);
}
group.setAmount(group.getAmount() + a.getAmount());
}
return new ArrayList<Activity>(groupMap.values());
}
Is it a WTF to use the DateFormatter in this way?
I'm using the DateFormatter because each activityDate could have time information.
I would just use the date object itself as the key. If it it bothers you because the date object is mutable, then use its toString() value. No reason to go making formats.
If the issue is that you want to normalize the date by removing the time component, it would be much better to do that withing the Activity object and remove the time component. If the issue is still further that there are potential time zone issues, I would use JodaTime, but there is no object in the JDK currently that represents a pure date without time, so going with a string isn't outrageous, but it should be hidden behind a method in the Activity object and the fact that it is a date formatted string without a time component should be an implementation detail.
java.util.Date is a quite poor abstraction for your need; it is IMO fair to stick to strings if nothing better is around, HOWEVER Joda-time provides a good datatype for you: DateMidnight or alternatively LocalDate if Activity is strictly timezome-independant.
other than that, the code looks good to me, you might be able to shorten it a bit using an implementation of Multimap, to avoid messy null-checking code. to be honest, it doesn't get much shorter than your solution:
public List<Activity> groupedByDate(List<Activity> input) {
//group by day
final Multimap<DateMidnight, Activity> activityByDay
= Multimaps.index(input, new Function<Activity, DateMidnight>() {
#Override
public DateMidnight apply(Activity from) {
return new DateMidnight(from.activityDate);
}
});
//for each day, sum up amount
List<Activity> ret = Lists.newArrayList();
for (DateMidnight day : activityByDay.keySet()) {
Activity ins = new Activity();
ins.activityDate = day.toDate();
for (Activity activity : activityByDay.get(day)) {
ins.amount+=activity.amount;
}
}
return ret;
}
Why not simply create a HashMap<Date, Activity>() instead of the roundabout way with Strings?
Sorry, I didn't answer the question. The answer is: yes, unless I am an idiot ;)
You could do this using the Date as the key if you used a TreeMap and provided a Comparator that only compared the year, month and day and not the time.
As already mentioned the best solution is to represent your date with day precission. If this is not possible joda is nice library.
If you can ignore daylight saving time then grouping by date can be accomplished much easier. A unix time day is 86 400 s long. The timestamp does ignore leap seconds. (Your timer stops for one second or the leap second is distributed in some way.) All date values were day is equal are the same day:
int msPerDay = 86400 * 1000;
long day = new Date().getTime() / msPerDay
One minor point is to adjust the timezone. For my timezone CET (UTC/GMT +1 hour) the GMT day starts one our later:
new GregorianCalendar(2009, 10, 1, 1, 0).getTime().getTime() / msPerDay) ==
new GregorianCalendar(2009, 10, 2, 0, 59).getTime().getTime() / msPerDay) ==
new Date().getTime() / msPerDay
If the daylight saving time is significant the best way is to use joda. The rules are just to complicated and locale specific to implement.

Categories

Resources