I have a listview and want to countdown each item. My issue is when I scroll the countdown times jump around to incorrect items (so it shows another items countdown time) and there is no rhyme or reason to it? here is the code
private final Map<String, TextView> mcounterlist= new HashMap<String, TextView>();
Then in my getview on my adapater I do
String gmtFormat = "yyyy-MM-dd HH:mm:ss";
TimeZone tz = TimeZone.getDefault();
SimpleDateFormat sdf = new SimpleDateFormat(gmtFormat);
sdf.setTimeZone(tz);
Date dd = null;
try {
dd = sdf.parse(o.endAt);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Date now = new Date();
String sss = timeCalculate((dd.getTime() /1000)- (now.getTime() /1000) );
ea.setText("Time Left: " + sss);
TextView cdi = new TextView();
mcounterlist.put(o.id , cdi);
So at this point I I just run a repeating thread to update.
private final Runnable mRunnable = new Runnable() {
public void run() {
// TextView textView;
String gmtFormat = "yyyy-MM-dd HH:mm:ss";
TimeZone tz = TimeZone.getDefault() ;
SimpleDateFormat sdf = new SimpleDateFormat(gmtFormat);
sdf.setTimeZone(tz);
// if counters are active
if(mcounterlist.size() > 0)
{
for (int i = 0; i < m_orders.size() && i < mcounterlist.size() ;i++) {
Order o = m_orders.get(i);
TextView c = mcounterlist.get(o.id);
Date dd = null;
try {
dd = sdf.parse(o.endAt);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Date now = new Date();
long l = (dd.getTime() /1000)- (now.getTime() /1000);
String sss;
if (l < 0)
{
sss = "ENDED";
}
else
{
sss = timeCalculate(l);
}
if(l < 60 * 60 * 24)
{
c.setBackgroundColor(Color.parseColor("#E3170D"));
}
else
{
c.setBackgroundColor(Color.parseColor("#00000000"));
}
c.setText("Time Left: " + sss);
}
}
mHandler.postDelayed(this, 1000);
}
};
But when I scroll through my list, the textviews jump all over the place. I believe part of my issue is related to how I sort the list every 30 seconds, but the ID's of the items don't change. Is there anything obvious that is wrong?
Thanks.
So the issue is that the views in a listview get reused, the solution was to implement the following change the id to the position in my hashmap and put it in GETVIEW
mcounterlist.remove(position);
mcounterlist.put(position , ea);
You probably don't need to remove the position, but I left it in there since I spent a hour on this, and it works so I don't wnat to change anything:)
Then in my repeat task I need to exclude anyitem not visibe, so here is my handler code
int fp = lv.getFirstVisiblePosition() -1 < 0 ? 0 :lv.getFirstVisiblePosition() -1;
int lp = lv.getLastVisiblePosition();
for (int i = fp; i < mcounterlist.size() && i < lp;i++) {
//Log.i("TEST231231",String.valueOf(i));
if (i < lv.getFirstVisiblePosition() -1 )
{
continue;
}
if (i >= lv.getLastVisiblePosition())
{
continue;
}
//my adapter list
Order o = m_orders.get(i);
//since I set the position as the refereance, I can use that for the hashmap
TextView c = mcounterlist.get(i);
...
So in essance since the same textviews were getting recycled, I could not update all of them because items that were not on the list were sharing the active text boxes. To eliminate this issue, I check and only edit the textboxes for items that are visible.
Related
I am using androidplot to show a graph, the labels get repeated. i searched forums and stackoverflow haven't found any solution.
now i noticed, if arraysize for x-axis or y-axis is less than 10, the array values get duplicated.
The screenshots show the left axis repeating the value 0,1,2. x-axis values are getting repeated. What is your best suggestion on solving this repeating label issue? Any help would be grateful. If you need any further information let me know.
/**
* A simple XYPlot
*/
public class SimpleXYPlotActivity extends Activity {
private XYPlot plot;
String[] domainLabels;
String oldDateStr, newDateStr;
Date newDate;
int totalDays;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.graph_xy_plot_example);
// initialize our XYPlot reference:
plot = (XYPlot) findViewById(R.id.plot);
Intent intent = getIntent();
Bundle bd = intent.getExtras();
DateFormat format = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
if (bd != null) {
oldDateStr = (String) bd.get("START_DATE");
newDateStr = (String) bd.get("END_DATE");
plot.setTitle("From: "+oldDateStr+" To: "+newDateStr);
try {
Date date1 = format.parse(oldDateStr);
Date date2 = format.parse(newDateStr);
long diff = date2.getTime() - date1.getTime();
totalDays = Integer.parseInt(String.valueOf(TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS)));
System.out.println ("Days: " + TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS));
} catch (ParseException e) {
e.printStackTrace();
}
}
SimpleDateFormat formatterDateGraph = new SimpleDateFormat("MMM d");
SimpleDateFormat formatterDate = new SimpleDateFormat("yyyy-MM-dd");
try {
newDate = format.parse(newDateStr);
} catch (ParseException e) {
e.printStackTrace();
}
DatabaseHandler db = new DatabaseHandler(this);
Calendar cal = GregorianCalendar.getInstance();
cal.setTime(newDate);
domainLabels= new String[totalDays];
Number[] series1Numbers = new Number[totalDays];
//domain 0 set outside loop for oldDateStr
domainLabels[0]=String.valueOf(formatterDateGraph.format(newDate.getTime()));
List<Orders> reportForDayList = db.getReportByTranType(oldDateStr, oldDateStr,"1");
series1Numbers[0]=reportForDayList.size();
for (int i = 1; i <totalDays ; i++) {
cal.add(Calendar.DAY_OF_YEAR, -1);
domainLabels[i] = String.valueOf(formatterDateGraph.format(cal.getTime()));
//fetch ordercount for that day
reportForDayList = db.getReportByTranType(formatterDate.format(cal.getTime()),formatterDate.format(cal.getTime()),"1");
series1Numbers[i]=reportForDayList.size();
}
series1Numbers = reverseSeries(series1Numbers);
domainLabels = reverseDomain(domainLabels);
//reverseNumber array
// domainLabels = reverseNumber(domainLabels);
// turn the above arrays into XYSeries':
// (Y_VALS_ONLY means use the element index as the x value)
XYSeries series1 = new SimpleXYSeries(
Arrays.asList(series1Numbers), SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Sales");
/* XYSeries series2 = new SimpleXYSeries(
Arrays.asList(series2Numbers), SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Series2");*/
// create formatters to use for drawing a series using LineAndPointRenderer
// and configure them from xml:
LineAndPointFormatter series1Format = new LineAndPointFormatter(Color.RED, Color.GREEN, Color.BLUE, null);
LineAndPointFormatter series2Format = new LineAndPointFormatter(Color.RED, Color.GREEN, Color.BLUE, null);
// add an "dash" effect to the series2 line:
/* series2Format.getLinePaint().setPathEffect(new DashPathEffect(new float[] {
// always use DP when specifying pixel sizes, to keep things consistent across devices:
PixelUtils.dpToPix(20),
PixelUtils.dpToPix(15)}, 0));*/
// just for fun, add some smoothing to the lines:
// see: http://androidplot.com/smooth-curves-and-androidplot/
series1Format.setInterpolationParams(
new CatmullRomInterpolator.Params(10, CatmullRomInterpolator.Type.Centripetal));
series2Format.setInterpolationParams(
new CatmullRomInterpolator.Params(10, CatmullRomInterpolator.Type.Centripetal));
// add a new series' to the xyplot:
plot.addSeries(series1, series1Format);
// plot.addSeries(series2, series2Format);
plot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.LEFT).setFormat(new DecimalFormat("#"));
plot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.BOTTOM).setFormat(new Format() {
#Override
public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) {
int i = Math.round(((Number) obj).floatValue());
return toAppendTo.append(domainLabels[i]);
}
#Override
public Object parseObject(String source, ParsePosition pos) {
return null;
}
});
}
public static Number[] reverseSeries(Number[] a)
{
int l = a.length;
for (int j = 0; j < l / 2; j++)
{
Number temp = a[j];
a[j] = a[l - j - 1];
a[l - j - 1] = temp;
}
return a;
}
public static String[] reverseDomain(String[] a)
{
int l = a.length;
for (int j = 0; j < l / 2; j++)
{
String temp = a[j];
a[j] = a[l - j - 1];
a[l - j - 1] = temp;
}
return a;
}
}
You are creating the domain values by transforming a 6 day range into long values and then subdividing the total range within those values into 10 distinct segments: You can't get 10 day labels from a range of 6 days.
To solve this problem you can either reduce the number of domain segments you are displaying or show more days worth of data.
This question already has answers here:
Determine Whether Two Date Ranges Overlap
(39 answers)
Closed 5 years ago.
I have set of date ranges, I need to get the combined date range if any of the dates overlap in Java.
Given three sets of date ranges, if any of the dates overlap with another range of dates need to be combined.
Example:
20170101-20170331
20170101-20170430
20170430-20170501
Expected result is:
20170101-20170430
20170430-20170501
I have all the dates in String Variable. Can please any one help me to how to write the code for that. I have pasted below my code.
I want to achieve the expected results. I couldn't find out how I need to modify this code. I am a beginner, please help me to do that. I have got this sample program from StackOverflow.
package com.kkkkk.Combine;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
public class Ideone {
public static void main(String[] args) throws java.lang.Exception {
ArrayList<Interval> x = new ArrayList<>();
x.add(new Interval("20170430", "20170501")); // "20170101", "20170430"
x.add(new Interval("20170101", "20170430"));// 20170101-20170430
x.add(new Interval("20170101", "20170331"));
x = merge(x);
for (Interval i1 : x) {
System.out.println(i1.getStartDate() + " " + i1.getEndDate());
}
}
public static ArrayList<Interval> merge(ArrayList<Interval> intervals) {
if (intervals.size() == 0 || intervals.size() == 1)
return intervals;
ArrayList<Interval> result = new ArrayList<Interval>();
Collections.sort(intervals, new IntervalComparator());
System.out.println("intervals ggggg\n" + intervals + "\n");
Interval first = intervals.get(0);
String start = first.getStartDate();
String end = first.getEndDate();
Date startDateF = null;
Date endDateF = null;
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
startDateF = sdf.parse(start);
endDateF = sdf.parse(end);
// ArrayList<Interval> result = new ArrayList<Interval>();
for (int i = 1; i < intervals.size(); i++) {
Interval current = intervals.get(i);
Date currentEndDate = sdf.parse(current.getEndDate());
Date currentStartDate = sdf.parse(current.getStartDate());
// if ((current.getStartDate().after(endDateF)) ||
Date d1 = minDate(endDateF, currentStartDate);
if ((currentStartDate).compareTo(endDateF) <= 0) {
endDateF = maxDate(currentEndDate, endDateF);
} else {
result.add(new Interval(start, (sdf.format(endDateF))));
// start = current.start;
// end = current.end;
start = sdf.format(currentStartDate);
endDateF = (currentEndDate);
enter code here
}
}
result.add(new Interval(start, end));
// result.add(new Interval(start, (sdf.format(endDateF))));
}
catch (ParseException ex) {
ex.printStackTrace();
}
// result.add(new Interval(start, end));
return result;
// return intervals;
}
public static Date minDate(Date date1, Date date2) {
// if date1 before date2 then return date1 else return date2
return date1.before(date2) ? date1 : date2;
}
/**
* find Max Dates
*
* #param date1
* #param date2
* #return
*/
public static Date maxDate(Date date1, Date date2) {
// if date1 after date2 then return date1 else return date2
System.out.println("date max");
return date1.after(date2) ? date1 : date2;
}
}
ISO 8601
Use standard ISO 8601 formats when serializing date-time values to text. Your format complies with the “basic” version of the standard, but better to use the full format when possible:
YYYY-MM-DD
Use the standard format for a date range, using a slash character as separator:
YYYY-MM-DD/YYYY-MM-DD
If you cannot alter the input strings, split the string on the hyphen. Parse each piece as a LocalDate. Use those objects to instantiate a LocalDateRange.
LocalDate ld = LocalDate.parse( "20170101" , DateTimeFormatter.BASIC_ISO_DATE ) ;
LocalDateRange
Use the LocalDateRange class from the ThreeTen-Extra project which extends java.time class functionality. Uses the standard format when parsing and generating text.
LocalDateRange range = LocalDateRange.parse( "2017-01-01/2017-03-31" ) ;
Collect in a List<LocalDateRange>.
To sort, write a comparator that calls LocalDateRange::getStart.
Compare to another range to see if they overlap. If so, combine with a call to union.
if ( range.overlaps( otherRange ) ) {
range = range.union( otherRange ) ;
}
If they do not overlap, you have finished that round. Store this result in another List<LocalDateRange>. Start another round with the next range.
Lather, rinse, repeat.
I assume your Interval is something like this:
private static class Interval {
private String begin;
private String end;
public Interval(String begin, String end) {
this.begin = begin;
this.end = end;
}
public String getStartDate() {
return begin;
}
public String getEndDate() {
return end;
}
}
What you need to do is to merge a Interval list. A solution is sort list with start date then end date. And then store the earliest start time and latest end time in a cursor variable. A example:
public List<Interval> merge(List<Interval> intervals) {
Collections.sort(intervals, new Comparator<Interval>() {
#Override
public int compare(Interval o1, Interval o2) {
if (o1.getStartDate().equals(o2.getStartDate())) {
return o1.getEndDate().compareTo(o2.getEndDate());
}
return o1.getStartDate().compareTo(o2.getStartDate());
}
});
List<Interval> ret = new ArrayList<>();
String MAX_VAL = "99999999";
String MIN_VAL = "00000000";
String start = MAX_VAL, end = MIN_VAL;
for (Interval interval : intervals) {
if (interval.getStartDate().compareTo(end) > 0) {
if (start.compareTo(MAX_VAL) < 0) {
ret.add(new Interval(start, end));
}
start = interval.getStartDate();
end = interval.getEndDate();
} else {
if (start.compareTo(interval.getStartDate()) < 0) {
start = interval.getStartDate();
}
if (end.compareTo(interval.getEndDate()) > 0) {
end = interval.getEndDate();
}
}
}
if (start.compareTo(MAX_VAL) < 0) {
ret.add(new Interval(start, end));
}
return ret;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
ArrayList<MainLab.Interval> list = new ArrayList<MainLab.Interval>();
list.add(new MainLab.Interval("20170430", "20170501"));
list.add(new MainLab.Interval("20170101", "20170430"));
list.add(new MainLab.Interval("20170101", "20170331"));
for (Iterator iterator = mergeInterval(list).iterator(); iterator.hasNext();) {
Interval interval = (Interval) iterator.next();
System.out.println(interval.getStart()+ "==="+interval.getEnd());
}
}
public static List<Interval> mergeInterval(ArrayList<MainLab.Interval> list){
/*
* Sort the list , Interval class have implemented Comparable Interface.
* So we will get sorted intervals. Intervals sorted based on start of interval
*/
Collections.sort(list);
Set<MainLab.Interval> resultlist = new TreeSet<MainLab.Interval>();
List<MainLab.Interval> mergedIntervals = new ArrayList<MainLab.Interval>();
//declare date formate to parse and format date from string to and from
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
if(list.size() == 1){
//resultlist = list
return list;
}
if(list.size() > 1){
// get first interval Object. conside it as first interval
Interval mergeInterval = list.get(0);
// loop other intervals from second in the list
for(int i=1; i< list.size() ; i++){
Interval interval2 = list.get(i);
try{
Date startDate1 = sdf.parse(mergeInterval.getStart());
Date endDate1 = sdf.parse(mergeInterval.getEnd());
Date startDate2 = sdf.parse(interval2.getStart());
Date endDate2 = sdf.parse(interval2.getEnd());
// compare if current interval's start date is before merging interval's end date
// then the two intervals are overlaping
if(startDate2.compareTo(endDate1) < 0 ){
// check whether end date of current loop interval is after the merging interval.
// then we need to update the end date of merging interval with looping interval's end date
if(endDate2.compareTo(endDate1) > 0 ){
mergeInterval.setEnd(interval2.getEnd());
}
}else{
// compare if current interval's start date is after merging interval's end date
// then it must be a new interval start so swap mergInterval variable with current looping interval
mergeInterval = interval2;
}
//add merge interval to set.
resultlist.add(mergeInterval);
}catch(Exception ex){
ex.printStackTrace();
}
}
}
mergedIntervals.addAll(resultlist);
return mergedIntervals;
}
public static class Interval implements Comparable<Interval>{
private String start;
private String end;
public String getStart() {
return start;
}
public void setStart(String start) {
this.start = start;
}
public String getEnd() {
return end;
}
public void setEnd(String end) {
this.end = end;
}
public Interval(){
}
public Interval(String start,String end){
this.start = start;
this.end = end;
}
#Override
public boolean equals(Object obj) {
// TODO Auto-generated method stub
Interval inteval = (Interval)obj;
return this.getStart().equals(inteval.getStart()) && this.getEnd().equals(inteval.getEnd()) ;
}
#Override
public int compareTo(Interval o) {
// TODO Auto-generated method stub
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
try{
Date startDate = sdf.parse(start);
Date endDate = sdf.parse(end);
Date pstartDate = sdf.parse(o.start);
Date pendDate = sdf.parse(o.end);
return startDate.compareTo(pstartDate);
}catch(Exception ex){
ex.printStackTrace();
}
return 0;
}
}
When I send "M" String to the Device I call time function from where I make my String.
Code:
` mManButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
man = 1;
clearScreen();
mManButton.setBackgroundResource(R.color.button_pressed);
mStartButton.setBackgroundResource(R.color.button_default);
mCalButton.setBackgroundResource(R.color.button_default);
mTestButton.setBackgroundResource(R.color.button_default);
mLinearButtton.setBackgroundResource(R.color.button_default);
mAutoButton.setBackgroundResource(R.color.button_default);
// Send a message using content of the edit text widget
sendMessage("M");
time();
}
});`
Then the time() function is called.
Here if my day is Monday then the variable day is set to 1.
That means in this function I am creating a String which has Date Format values in it. This string starts from "A" and ends with "B".
Code :
private void time()
{
int day = 0;
Date now = new Date();
String sdf = new SimpleDateFormat("EEEE", Locale.ENGLISH).format(now);
switch(sdf){
case ("Monday"):
day = 1;
break;
case("Tuesday"):
day = 2;
break;
case ("Wednesday"):
day = 3;
break;
case ("Thursday"):
day = 4;
break;
case("Friday"):
day = 5;
break;
case ("Saturday"):
day = 6;
break;
case("Sunday"):
day = 7;
break;
}
int mm = Calendar.getInstance().get(Calendar.MINUTE);
int HH = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
int dd = Calendar.getInstance().get(Calendar.DAY_OF_MONTH);
int MM = Calendar.getInstance().get(Calendar.MONTH)+1;
int yy = Calendar.getInstance().get(Calendar.YEAR)%100;
if(mm<10) {
String time1 = "A" + "0" + mm + HH + "0" + day + dd + MM + yy + "B"; //suppose time1 = A041303211216B
tv7.setText("Please Wait..");
int p = 0;
while (p < time1.length())
{
char zx = time1.charAt(p);
String xz = String.valueOf(zx);
sendMessage(xz);
p++;
}
}
else if(mm>=10) {
String time2 = "A" + mm + HH + "0" + day + dd + MM + yy + "B"; **//suppose time2 = A151303211216B**
tv7.setText("Please Wait..");
int k = 0;
while (k < time2.length())
{
char zx = time2.charAt(k);
String xz = String.valueOf(zx);
sendMessage(xz);
k++;
}
}
}
When the string is created I send each characters of the string to sendMessage().
Code :
private void sendMessage(String message) {
// Check that we're actually connected before trying anything
if (mChatService.getState() !=
com.example.hasani.bluetoothterminal.BluetoothChatService.STATE_CONNECTED) {
Toast.makeText(getActivity(), R.string.not_connected, Toast.LENGTH_SHORT).show();
mStartButton.setBackgroundResource(R.color.button_default);
mCalButton.setBackgroundResource(R.color.button_default);
mTestButton.setBackgroundResource(R.color.button_default);
mManButton.setBackgroundResource(R.color.button_default);
mAutoButton.setBackgroundResource(R.color.button_default);
return;
}
// Check that there's actually something to send
if (message.length() > 0) {
// Get the message bytes and tell the BluetoothChatService to write
byte[] send = message.getBytes();
mChatService.write(send);
// Reset out string buffer to zero and clear the edit text field
mOutStringBuffer.setLength(0);
}
}
The write function.
Code :
public void write(byte[] out) {
// Create temporary object
ConnectedThread r;
// Synchronize a copy of the ConnectedThread
synchronized (this) {
if (mState != STATE_CONNECTED) return;
r = mConnectedThread;
}
// Perform the write unsynchronized
r.write(out);
}
The wite in ConnectedThread
Code :
public void write(byte[] buffer) {
try {
mmOutStream.write(buffer);
// Share the sent message back to the UI Activity
mHandler.obtainMessage(com.example.hasani.bluetoothterminal.Constants.MESSAGE_WRITE, -1, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Log.e(TAG, "Exception during write", e);
}
}
As there is a role of Handler in it.
The issue is when debugging step by step, each character is sent to the other Device and that device receives each and every string from "A" to "B", thus there is no problem.
But when i run My android app, after sending "M", the time() function is called and the String is sent but the first three characters of the string i.e; "Amm" is not received by the device.
I still don't understand what is causing the problem.
Please Help!. Will be appreciated. Thank You!
Ohkay wait!!! I got the solution. In case if someone go through the same kind of situation.
In my onClickListener I call my time() function after a 5 second delay using a second handler.
My onClickListener code is :
mManButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
man = 1;
linear = 0;
auto = 0;
cal = 0;
test = 0;
linear = 0;
clearScreen();
mManButton.setBackgroundResource(R.color.button_pressed);
mStartButton.setBackgroundResource(R.color.button_default);
mCalButton.setBackgroundResource(R.color.button_default);
mTestButton.setBackgroundResource(R.color.button_default);
mLinearButtton.setBackgroundResource(R.color.button_default);
mAutoButton.setBackgroundResource(R.color.button_default);
// Send a message using content of the edit text widget
sendMessage("M");
tv7.setText("Please wait....");
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
time();
}
},5000);
}
});
My time() function is :
private void time() {
int day = 0;
Date now = new Date();
String sdf = new SimpleDateFormat("EEEE", Locale.ENGLISH).format(now);
switch (sdf) {
case ("Monday"):
day = 1;
break;
case ("Tuesday"):
day = 2;
break;
case ("Wednesday"):
day = 3;
break;
case ("Thursday"):
day = 4;
break;
case ("Friday"):
day = 5;
break;
case ("Saturday"):
day = 6;
break;
case ("Sunday"):
day = 7;
break;
}
int mm = Calendar.getInstance().get(Calendar.MINUTE);
int HH = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
int dd = Calendar.getInstance().get(Calendar.DAY_OF_MONTH);
int MM = Calendar.getInstance().get(Calendar.MONTH)+1;
int yy = Calendar.getInstance().get(Calendar.YEAR)%100;
String A = "A";
String min = String.format("%02d",mm);
String hour = String.format("%02d",HH);
String d = String.format("%02d",day);
String date = String.format("%02d",dd);
String month = String.format("%02d",MM);
String year = String.format("%02d",yy);
String B = "B";
String time2 = A+min+hour+d+date+month+year+B;
sendMessage(time2);
}
Now i can receive correct data as I required. My application works like a charm.
To expand on my comment, the simplest way to handle waiting to connect would be thus. First, return success or failure from write():
public boolean write(byte[] out) {
// Create temporary object
ConnectedThread r;
// Synchronize a copy of the ConnectedThread
synchronized (this) {
if (mState != STATE_CONNECTED) return false;
r = mConnectedThread;
}
// Perform the write unsynchronized
r.write(out);
return true;
}
Then in sendMessage(), replace mChatService.write(send); with:
while (!mChatService.write(send))
{
try {
Thread.sleep(10);
}
catch(InterruptedException ex) {
// Uncomment to just give up
//break;
}
}
This will wait another 10 milliseconds or so before trying to resend.
There's of course a lot of improvements to make like only allowing a few retries before giving up completely, etc.
On a related note, with the above change you can probably do:
sendMessage(time1);
instead of doing it a character at a time.
Finally, your time formatting can be simplified to:
Calendar cal = Calendar.getInstance();
Date date = cal.getTime();
SimpleDateFormat format = new SimpleDateFormat("mmHHcddMMYY");
String time = "A" + format1.format(date) + "B";
Or something like that. See this page for details.
Suppose time is given in MM:SS(ex- 02:30) OR HH:MM:SS in String format.how can we convert this time to second.
In your case, using your example you could use something like the following:
String time = "02:30"; //mm:ss
String[] units = time.split(":"); //will break the string up into an array
int minutes = Integer.parseInt(units[0]); //first element
int seconds = Integer.parseInt(units[1]); //second element
int duration = 60 * minutes + seconds; //add up our values
If you want to include hours just modify the code above and multiply hours by 3600 which is the number of seconds in an hour.
public class TimeToSeconds {
// given: mm:ss or hh:mm:ss or hhh:mm:ss, return number of seconds.
// bad input throws NumberFormatException.
// bad includes: "", null, :50, 5:-4
public static long parseTime(String str) throws NumberFormatException {
if (str == null)
throw new NumberFormatException("parseTimeString null str");
if (str.isEmpty())
throw new NumberFormatException("parseTimeString empty str");
int h = 0;
int m, s;
String units[] = str.split(":");
assert (units.length == 2 || units.length == 3);
switch (units.length) {
case 2:
// mm:ss
m = Integer.parseInt(units[0]);
s = Integer.parseInt(units[1]);
break;
case 3:
// hh:mm:ss
h = Integer.parseInt(units[0]);
m = Integer.parseInt(units[1]);
s = Integer.parseInt(units[2]);
break;
default:
throw new NumberFormatException("parseTimeString failed:" + str);
}
if (m<0 || m>60 || s<0 || s>60 || h<0)
throw new NumberFormatException("parseTimeString range error:" + str);
return h * 3600 + m * 60 + s;
}
// given time string (hours:minutes:seconds, or mm:ss, return number of seconds.
public static long parseTimeStringToSeconds(String str) {
try {
return parseTime(str);
} catch (NumberFormatException nfe) {
return 0;
}
}
}
import org.junit.Test;
import static org.junit.Assert.*;
public class TimeToSecondsTest {
#Test
public void parseTimeStringToSeconds() {
assertEquals(TimeToSeconds.parseTimeStringToSeconds("1:00"), 60);
assertEquals(TimeToSeconds.parseTimeStringToSeconds("00:55"), 55);
assertEquals(TimeToSeconds.parseTimeStringToSeconds("5:55"), 5 * 60 + 55);
assertEquals(TimeToSeconds.parseTimeStringToSeconds(""), 0);
assertEquals(TimeToSeconds.parseTimeStringToSeconds("6:01:05"), 6 * 3600 + 1*60 + 5);
}
#Test
public void parseTime() {
// make sure all these tests fail.
String fails[] = {null, "", "abc", ":::", "A:B:C", "1:2:3:4", "1:99", "1:99:05", ":50", "-4:32", "-99:-2:4", "2.2:30"};
for (String t: fails)
{
try {
long seconds = TimeToSeconds.parseTime(t);
assertFalse("FAIL: Expected failure:"+t+" got "+seconds, true);
} catch (NumberFormatException nfe)
{
assertNotNull(nfe);
assertTrue(nfe instanceof NumberFormatException);
// expected this nfe.
}
}
}
}
int v = 0;
for (var x: t.split(":")) {
v = v * 60 + new Byte(x);
}
This snippet should support HH:MM:SS (v would result in seconds) or HH:MM (v would be in minutes)
try this
hours = totalSecs / 3600;
minutes = (totalSecs % 3600) / 60;
seconds = totalSecs % 60;
timeString = String.format("%02d",seconds);
private static final String TIME_FORMAT = "hh:mm a";//give whatever format you want.
//Function calling
long timeInMillis = TimeUtils.getCurrentTimeInMillis("04:21 PM");
long seconds = timeInMillis/1000;
//Util Function
public static long getCurrentTimeInMillis(String time) {
SimpleDateFormat sdf = new SimpleDateFormat(TIME_FORMAT, Locale.getDefault());
// sdf.setTimeZone(TimeZone.getTimeZone("GMT")); //getting exact milliseconds at GMT
// sdf.setTimeZone(TimeZone.getDefault());
Date date = null;
try {
date = sdf.parse(time);
} catch (ParseException e) {
e.printStackTrace();
}
return date.getTime();
}
I have written an extension function in Kotlin for converting String to seconds
fun String?.converTimeToSeconds(): Int {
if (this.isNullOrEmpty().not()) {
val units = this?.split(":")?.toTypedArray()
if (units?.isNotEmpty() == true && units.size >= 3) {
val hours = units[0].toInt()
val minutes = units[1].toInt()
val seconds = units[2].toInt()
return (3660 * hours) + (60 * minutes) + seconds
}
}
return 0
}
I want to randomly generate times and numbers.. Here I used hashmap generate some records. Now I can generate the numbers but I cant separate them. I have to separate the values so that I can set those in database..
Here is my code...
public class DateTimePopulation {
private Random rand = new Random();
private Date theDay;
private String callDuration = null;
private String endDay = null;
SimpleDateFormat mytimeFormat = new SimpleDateFormat("HH:mm:ss");
public static void main(String[] args) throws ParseException {
DateTimePopulation d = new DateTimePopulation();
for (int i = 1; i <= 3; i++) {
Map rec = d.getRecord();
for (int j = 0; j < rec.size(); j++) {
Collection c = rec.values();
Iterator itr = c.iterator();
int count=0;
while (itr.hasNext()) {
Object element=itr.next();
System.out.println(element);
}
System.out.println();
}
}
}
private Map getRecord() {
Map<String, Object> rec = new LinkedHashMap<String, Object>();
Date startDate;
try {
startDate = getRandStartDate();
rec.put("StartTime", startDate);
int start = 7200000, end = 0;
int duration = getRandDuration(start, end);
rec.put("Duration", duration);
Date endDate = getRandEndDate(startDate, duration);
rec.put("EndTime", endDate);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return rec;
}
private Date getRandEndDate(Date startDate, int duration) {
Random r = new Random();
int ranSec = r.nextInt(duration - 0) + 0;
return new Date(startDate.getTime() + ranSec * 1000);
}
private int getRandDuration(int High, int Low) {
Random r = new Random();
return r.nextInt(High - Low) + Low;
}
private Date getRandStartDate() throws ParseException {
Date theDay = new SimpleDateFormat("yyyyMMdd hh:mm:ss")
.parse("20130101 00:00:00");
int High = 60 * 60 * 24 * 30 * 6;
Random r = new Random();
int Low = 10;
int R = r.nextInt(High - Low) + Low;
return new Date(theDay.getTime() + R * 1000);
}
}
Here is the output. I am showing 2 set of it. I have to separate the time, duration etc.
Tue Jan 08 11:01:57 IST 2013
6074479
Fri Jan 18 12:56:24 IST 2013
Firstly, your design is strange to start with - why are you calling getRecord() on an instance, when it doesn't do anything with the fields of the object you're calling it on?
Additionally, when you're iterating over a map, you're actually iterating over the same map 3 times:
for (int j = 0; j < rec.size(); j++) {
Collection c = rec.values();
Iterator itr = c.iterator();
int count=0;
while (itr.hasNext()) {
Object element=itr.next();
System.out.println(element);
}
System.out.println();
}
Your outer loop is pointless here - you're never using j, after all. I would probably iterate over the entries rather than the values, if you really want to - then you can print out the key which goes with each value.
Next, I would encourage you not to use a map for this at all - create a separate type with fields for start time, duration and end time. That will fix things very simply.
Next, if you still want to use a map, stop using the raw types - it'll make your life simpler.
Finally, if you really still want to use a map, you already know the keys, so there's no point in iterating over it:
System.out.println("Start: " + map.get("StartTime");
System.out.println("Duration: " + map.get("Duration");
System.out.println("End: " + map.get("EndTime");
Basically, I strongly suggest that you take a step back and revisit your whole design. You may well find it's better to start from scratch than to change your existing code.
Try to generify this code:
private Map getRecord() {
Map<String, Object> rec = new LinkedHashMap<String, Object>();
Date startDate;
try {
startDate = getRandStartDate();
rec.put("StartTime", startDate);
int start = 7200000, end = 0;
int duration = getRandDuration(start, end);
rec.put("Duration", duration);
Date endDate = getRandEndDate(startDate, duration);
rec.put("EndTime", endDate);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return rec;
}
Something like that:
private DateInterval getRecord() {
DateInterval interval = null;
try {
Date startDate = getRandStartDate();
int start = 7200000, end = 0;
int duration = getRandDuration(start, end);
Date endDate = getRandEndDate(startDate, duration);
interval = new DateInterval(startDate, endDate, duration);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return interval;
}
See also:
public class DateInterval {
private Date startDate;
private Date endDate;
private int duration;
public DateInterval(Date startDate, Date endDate, int duration) {
this.startDate = startDate;
this.endDate = endDate;
this.duration = duration;
}
public Date getStartDate() {
return startDate;
}
public Date getEndDate() {
return endDate;
}
public int getDuration() {
return duration;
}
}
I mean, you don't need Map for this purpose, use the your own entity. If you need to hold all your entities at Collection, use Map with DB UUIDs as a keys or List.