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

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?

Related

CalendarArray get dates betweeen two Dates and skip a few

i am trying to create an Array of Calendar Objects where i get all dates between start and end, while skipping the date "skip". So let's imagine i have the dates:
start = 04.03.2016
skip = 21.07.2016
end = 02.03.2017
i tried something like this, but it didn't work that well:
public static Calendar[] getRange(Calendar start, Calendar skip, Calendar end){
Calendar[] daysRange = new Calendar[100];
Calendar placeholder = Calendar.getInstance();
while(start.before(end)){
if(placeholder.getTime() == skip.getTime()){
continue;
} placeholder.add(Calendar.Date, 1);
}
//(pseudocode)
//add placeholder to daysRange
return daysRange;
}
I would appreciate any tips on how i could continue.
Thanks!
First:
while (start.before(end)) {
You never modify start or end, so the loop is endless.
Second: you use one placeholder object, that means that your whole array points to that one object, create a new Calendar for every step en the loop.
Third: don't use an array, use an ArrayList.

Count occurrences of an approximate date in an entity

I need to count the points of a chart for a duration picked by an user.
My chart is about logs, we need to know how many users are connected for every specified minutes while a specific duration. We don't want to use too many queries, so I work essentially with lists.
Dates are stored in String format as "yyyy-MM-dd HH:mm:ss".
My code works but is really too long to load:
old=ofy().load().type(Log.class).filter("site in",selectedSites).filter("license in",ofy().load().type(License.class).filter("name", name)).filter("date_out >=",datemin).filter("date_out <=",datemax).list();
Duration duration = new Duration(firstIn, lastDateOut); //Duration between two dates choosen by the user
int dimension=(int) ((duration.getStandardMinutes())/divideBy); //Number of abscissa points in the chart
DateTime[] dates=new DateTime[dimension+1]; //Init of the dates
int[] counts=new int[dimension+1]; //Init of the count table (count of logged users at the date
DateTime transfert=firstIn; //First date
for(int i=0;i<=dimension;i++){
counts[i]=0;
dates[i]=transfert.minusSeconds(transfert.getSecondOfMinute());
transfert=transfert.plusMinutes(divideBy);
for(Log log:old){
if((StaticMethods.toDateTime(log.getDate_in()).minusSeconds(StaticMethods.toDateTime(log.getDate_in()).getSecondOfMinute()).equals(dates[i]))
||((StaticMethods.toDateTime(log.getDate_in()).minusSeconds(StaticMethods.toDateTime(log.getDate_in()).getSecondOfMinute()).isBefore(dates[i]))
&&(StaticMethods.toDateTime(log.getDate_out()).minusSeconds(StaticMethods.toDateTime(log.getDate_out()).getSecondOfMinute()).isAfter(dates[i])))
||(StaticMethods.toDateTime(log.getDate_out()).minusSeconds(StaticMethods.toDateTime(log.getDate_out()).getSecondOfMinute()).equals(dates[i]))
){
counts[i]++;
}
}
GraphData nw=new GraphData(dates[i].toDate(), counts[i]);
}
I want to know if there is a possible less loading time (have read this and I need to know if there's similar way for approximate values).
you should order your data by Date_out value first, in ascending order. Also you don't need tables for Dates and Counts, try the following instead
Duration duration = new Duration(firstIn, lastDateOut); //Duration between two dates choosen by the user
int dimension=(int) ((duration.getStandardMinutes())/divideBy); //Number of abscissa points in the chart
DateTime transfert=firstIn; //First date
DateTime currentDate=transfert; // X-Axis Date
int currentCount=0; // Y-Axis LoggedUser Count
//Log data
DateTime log_DateIn;
DateTime log_DateOut;
for(int i=0;i<=dimension;i++)
{
currentDate = transfert;
currentCount = 0;
transfert = transfert.plusMinutes(divideBy);
for(Log log:old)
{
// We store our dates into variables, that way we avoid doing the time conversion twice
log_DateIn = StaticMethods.toDateTime(log.getDate_in()).minusSeconds(StaticMethods.toDateTime(log.getDate_in()).getSecondOfMinute());
log_DateOut = StaticMethods.toDateTime(log.getDate_out()).minusSeconds(StaticMethods.toDateTime(log.getDate_out()).getSecondOfMinute());
// Since we made the list ordered by DateOut, we are sure that if the stored DateOut is greater than transfert we can't find another user, that way we can break the for without parsing each log
if(log_DateOut.isAfter(transfert))
break;
// Now we can do checks to see if we need to increase the count
// We just check if the DateIn is between the currentDate and currentDate + divideBy (transfert)
if(log_DateIn.isAfter(currentDate) && log_DateIn.isBefore(transfert))
currentCount++;
// Same thing for DateOut
else if(log_DateOut.isAfter(currentDate) && log_DateOut.isBefore(transfert))
currentCount++;
// Now we need both cases
else if(log_DateIn.isBefore(currentDate) && log_DateOut.isAfter(transfert))
currentCount++;
// Equalities
else if(log_DateIn.equals(currentDate) || log_DateIn.equals(transfert) || log_DateOut.equals(currentDate) || log_DateOut.equals(transfert))
currentCount++;
}
GraphData nw = new GraphData(currentDate, currentCount);
}

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));
}

Sorting out the dates in chronological order

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.

Parsing a List<List<String>> in Android?

I'm developing a custom Adsense report tool using Google Java Client Library for Android. I've successfully authenticated and can make API calls to the server. but now when I receive the response, I don't know how to parse it and correctly show the result to user.
According to the javaDocs, AdsenseReportsGenerateResponse.getRows() generates a List> But I'm kinda lost how to properly parse it to get:
-Today's earnings
-Yesterday's earnings
-Last 7 days
-Last month
-From the beginning of time
Here's part of my code related to the question
Reports.Generate request = adsense.reports().generate(startDate, endDate);
request.setMetric(Arrays.asList("PAGE_VIEWS", "AD_REQUESTS", "AD_REQUESTS_COVERAGE", "CLICKS",
"AD_REQUESTS_CTR", "COST_PER_CLICK", "AD_REQUESTS_RPM", "EARNINGS"));
request.setDimension(Arrays.asList("DATE", "WEEK", "MONTH"));
request.setSort(Arrays.asList("+DATE"));
AdsenseReportsGenerateResponse response = request.execute();
//TODO: Here be dragons
response.getRows();
Edit: Here is the javaDoc which mentions the getRow()
Hmm it seems nobody on this site can help?!
You should find our sample code useful: http://code.google.com/p/google-api-java-client/wiki/APIs#AdSense_Management_API
Namely, this is the file you're interested in: http://code.google.com/p/google-api-java-client/source/browse/adsense-cmdline-sample/src/main/java/com/google/api/services/samples/adsense/cmdline/GenerateReport.java?repo=samples
Here's a snippet of code to print the output. Mind you, this is for a command line application, but should be easily adaptable:
if ((response.getRows() != null) && !response.getRows().isEmpty()) {
// Display headers.
for (AdsenseReportsGenerateResponseHeaders header : response.getHeaders()) {
System.out.printf("%25s", header.getName());
}
System.out.println();
// Display results.
for (List<String> row : response.getRows()) {
for (String column : row) {
System.out.printf("%25s", column);
}
System.out.println();
}
System.out.println();
} else {
System.out.println("No rows returned.");
}
As for getting the data for different periods of time, you should probably be running different reports, not cramming it all into one, as that would take different start dates and end dates. Here's how it works:
Today's earnings: set the start and end dates to today, set the dimension list to just DATE
Yesterday's earnings: set the start and end date to yesterday, set the dimension list to just DATE
Last 7 days: if you want data per day, then you set the start date to 7 days ago, the end date to today, and the dimension list to just DATE. If you want to aggregate the stats, you may need to calculate this yourself, as WEEK and MONTH refer to a calendar week and month, not the last 7 days.
Last month: start date 1st of last month, end date last day of the month, dimension MONTH.
All time: how do you want this aggregated? Per month? Then set the start date to, say, 1980-1-1, end date to today and dimension to MONTH.
This blog post should help with understanding reporting concepts a bit better: http://adsenseapi.blogspot.com/2011/11/adsense-management-api-diving-into.html
Let me know if you need help with anything else!
Its not a List<List> as far as I understand the api. Try this:
String[][] array = response.getRows();
for (int i = 0; i < array.getSize(); i++){
String dimension = array[i][0];
String metric = array[i][1];
//Do what you want with them
}
I am writing this because the API says it has a list of dimensions with one value for the string and one for the metric, as far as I understand.
If you expect several cells on each row (Which I believe the API doesn't work that way), you need to add another for inside and get the size of the current list probably with something like array[i].getSize()
Post back if it doesn't help you.
Edit: I see now. Try this:
List list = response.getRows();
for (int i = 0; i < list.size(); i++){
List<String> list2 = list.get(i);
for (int j = 0; j < list2.size(); j++){
String value = list2.get(j);
//Do what you want
}
}

Categories

Resources