Following is a piece of code that I am running.
#Test
public void testMyMehotd() {
String expected = "2012-09-12T20:13:47.796327Z";
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'");
//df.setTimeZone(TimeZone.getTimeZone("UTC"));
Date d = null;
try {
d = df.parse(expected);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return;
}
String actual = df.format(d);
System.out.println(expected);
System.out.println(actual);
}
but the output is different than what I expect.
expected : 2012-09-12T20:13:47.796327Z
actual : 2012-09-12T20:27:03.000327Z
Can someone tell me the reason for this and what is the solution.
Thanks in advance.
Whenever you exceed 999 milliseconds, DateFormat will try to add the remaining milliseconds to your date. Consider the following simpler example:
String expected = "2012-09-12T20:13:47.1001Z";
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSS'Z'");
Date d = df.parse(expected);
The resulting date will be 2012-09-12T20:13:48.0001. That is, since you have 1001 milliseconds, you get 1 extra second (1000 milliseconds), and 1 millisecond (1001 % 1000). Thus instead of 47 seconds as in the original date, you get 48 seconds.
This is also what happens if you try to parse a date with an invalid number of days in a month. For example, if you try to add an extra day to September, and parse 2012-09-31:
String expected = "2012-09-31";
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
Date d = df.parse(expected);
System.out.println(df.format(d));
You'll actually get 2012-10-01. Again, that's because DateFormat will detect that the 31st day of September is not valid, and will try to use heuristics to transform the Date, thus adding one day, ending up with the first day of the next month.
There's an option to tell the parser not to use these heuristics, by setting lenient mode to false with:
df.setLenient(false);
However, using this mode, both above examples will throw a ParseException.
S means millisecond and you passed 796327 milliseconds. That number is equal to 13[min]:16[sec]:327[millis] so additional minutes and seconds ware added to your date.
Related
I have written this sample program where I want to convert a date into another format. I don't see the expected date when using simple date format.
public class TestDate {
/**
* #param args
*/
public static void main(String[] args) {
SimpleDateFormat originalformat = new SimpleDateFormat("yyyy-MM-dd-HH.mm.ss.SSSSSS");
SimpleDateFormat targetformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS");
try {
//Use Simple Date Format
Date date = originalformat.parse("2015-04-09-17.18.48.677862");
System.out.println("Using SDF "+targetformat.format(date));
//Use Manual Translation
String eventTime = "2015-04-09-17.18.48.677862";
StringBuffer timeBuffer = new StringBuffer();
for (int i = 0; i < eventTime.length(); i++) {
if (i == 10) {
timeBuffer.append(" ");
continue;
} else if (i == 13 || i == 16) {
timeBuffer.append(":");
continue;
} else {
timeBuffer.append(eventTime.charAt(i));
}
}
timeBuffer.append("000");
String transformedTime = timeBuffer.toString().trim();
System.out.println("Manual Translation "+transformedTime);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I see the following outputs. The first logic is using simple date format and the second one is manual translation.
Using SDF 2015-04-09 17:30:05.000862
Manual Translation 2015-04-09 17:18:48.677862000
So How to make the simple date format to output a exactly similar value like the manual one
The value 677862 is being interpreted as milliseconds, as per the SimpleDateFormat javadocs, not as microseconds. That is 677 seconds, 862 milliseconds. The seconds part is 11 minutes and 17 seconds, which is added to 17.18.48 to become 17.30.05.
To work with the S format, you will need 3 digits for the milliseconds, not 6. You will need to truncate your string to 3 digits past the last decimal point.
It would appear that you can't use 6 digits for the milliseconds. Your program is 11 minutes and 17 seconds off. 660 seconds = 11 minutes and you have 17 seconds off. So its just converting your input into minutes from seconds since it can't accept more than 3 milliseconds digits.
How to display only hours and using int variable? I mean print time like 20:30:44 PM, I want to store only hours, mean 20 in int variable. how to do that?
Can anybody tell me the code if you know, thanks?
Try using Calendar's get method like:
Calendar c = ..
c.setTime(...);//if you have time in long coming from somewhere else
int hour = c.get(Calendar.HOUR_OF_DAY);
If you try to parse time from String I recommend these solutions:
String time = "20:30:44 PM"; // this is your input string
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss aa");
try {
Date date = sdf.parse(time);
// this is the uglier solution
System.out.println("The hour is: "+date.getHours());
GregorianCalendar gc = new GregorianCalendar();
gc.setTime(date);
// this is nicer solution
System.out.println("The hour is: "+gc.get(Calendar.HOUR_OF_DAY));
} catch (ParseException e) {
System.err.println("Couldn't parse string! "+e.getMessage());
}
date.getHours() and gc.get(Calendar.HOUR_OF_DAY) return int, in this example I printed it out without creating variable.
You can, of course, use regular expression to find out hour in your string but above solutions should do the trick. You can learn more about SimpleDateFormat and available patterns here. I hope I helped you a bit.
EDIT: In his comment autor noted, that date isn't static (like in String) but dynamic:
Calendar calendar = new GregorianCalendar();
int hour = calendar.get(Calendar.HOUR_OF_DAY);
System.out.println("The hour is: "+hour);
I hope this helps.
I have a strange issue. The below code is executed in a while loop through a few times. Now, every so often, this sdf.parse returns 0s for the hours, minutes and seconds. An example of the dates look like this...
2014:3:7:8:0
2014:3:7:9:0
2014:3:7:10:0
2014:3:7:11:0
2014:3:7:12:0 * This returns 0's
2014:3:7:13:0
2014:3:7:14:0
Below is the code.
SimpleDateFormat sdf = new SimpleDateFormat("yyyy:M:d:h:m");
sdf.setTimeZone(TimeZone.getDefault());
Date sTime = null;
try {
sTime = sdf.parse(start);
} catch (ParseException e) {
e.printStackTrace();
return null;
}
I think 12 at hour position is getting read in 12h format, so it is the same as 0. Try H instead of h in pattern
SimpleDateFormat sdf = new SimpleDateFormat("yyyy:M:d:H:m");
'h' represents hour in 1-12 format. You should use 'H' (in upper case) instead if you want 0-23 format. Also you needn't explicitly set default time zone because by default it equals TimeZone.getDefault().
I am getting a date from JSON file, and it is in string format.I have two string values of date named startdate and enddate that is coming from intent to currentActivity. Now I want to check that, if date value coming from json file is after the startdate or before the enddate. How can I do this? And yes, the format I json file having is "yyyy-mm-dd".
JSON Data Look like:
{"posts":[{"start_date":"2013-02-15","end_date":"2013-02-21"}]}
Here is the code I have tried but I am getting output as Mon Jan 07 00:00:00 GMT+5:30 2013:
Intent intent = getIntent();
String startDate = intent.getStringExtra("startDate"); //I have check this. It is proper.
String endDate = intent.getStringExtra("endDate"); //I have check this. It is proper.
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date start = null,end = null;
try {
start = sdf.parse(startDate);
end = sdf.parse(endDate);
} catch (ParseException e1) {
e1.printStackTrace();
}
Here is the code of comparing date:
Date date = null;
try {
date = sdf.parse(c.getString(TAG_DATE)); //I am getting the date from a json file here.
} catch (ParseException e) {
e.printStackTrace();
}
Date currDate = new Date();
if (end.compareTo(currDate) < 0 || start.compareTo(currDate) < 0) {
Toast.makeText(getApplicationContext(),"Please select valid dates...",Toast.LENGTH_SHORT).show();
} else if (end.compareTo(currDate) == 0 && start.compareTo(currDate) >= 0){
if (date.after(start)) {
Toast.makeText(getApplicationContext(), "After...",Toast.LENGTH_SHORT).show();
}
} else if (end.compareTo(currDate) > 0 && start.compareTo(currDate) >= 0) {
if (date.after(start) && date.before(end)) {
Toast.makeText(getApplicationContext(),"Before...",Toast.LENGTH_SHORT).show();
}
}
I would prefer using a more robust approach that involves converting the date strings to actual Date (or Calendar) objects:
String startDateString = ...; // get date string from json
String endDateString = ...; // get date string from json
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
Date start = formatter.parse(startDateString);
Date end = formatter.parse(endDateString);
From here on, you can use e.g. start.before(end) or end.after(start) to check whether a date comes before or after another date. If you need more fine-grained control, you can always get the date in milliseconds and have your logic work on that.
So you've updated your code, but you're leaving it up to us to figure out what's going on and, more importantly, what you're expecting to happen? It looks like you want to check how the current date relates to those retrieved from json, although I'm a little lost at what the fourth date field, named date, is for.
Just some remarks about the current snippet:
if (end.compareTo(currDate) < 0 || start.compareTo(currDate) < 0)
Personally, I find before() and after() much more readable and descriptive, but I suppose there's nothing wrong with using compareTo(). However, important to realize is that 0 will only be returned iff the underlying millisecond representations of two dates are equal. With that being said, I'm not sure how much sense it would make to do the first check in the following condition:
else if (end.compareTo(currDate) == 0 && start.compareTo(currDate) >= 0)
You'll have to be really lucky to get the milliseconds of end exactly identical to currDate. Unless you do some manipulation somewhere to normalize all the dates to e.g. midnight, it's unlikely end.compareTo(currDate) == 0 will ever be true.
Regarding this normalization: have a look at the previously mentioned Calendar class. It'll allow you to easily retrieve the values for the separate fields of a datestamp/timestamp. For example, if you only want to compare the day, month and year, you can get those specific fields from a Calendar instance with a simple get call. Even more convenient is that you can also set every field independently - that's great for normalizing all dates to e.g. midnight or midday, after which you can still use the before() and after() methods.
I'm convinced that should give you enough pointers to correctly code up an implementation that fits your needs. Without exactly knowing what you're trying to achieve, I'm afraid I can't help you any further.
You can also try this:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
boolean isBefore = new Date().before(sdf.parse("2013-02-15",0));
http://developer.android.com/reference/java/text/SimpleDateFormat.html
http://developer.android.com/reference/java/util/Date.html
If you explode the date by dash - it will be easy to compare dates between mobile date and date by json. with easy compare logic you will get it.
String date = "2013-02-15";
String[] separated = date.split("-");
separated[0]; // this will contain "2013"
separated[1]; // this will contain "02"
separated[2]; // this will contain "15"
Calendar c1 = Calendar.getInstance();
String date = c1.get(Calendar.DAY_OF_MONTH);
Calendar ( to get mobile date )
http://developer.android.com/reference/java/util/Calendar.html
I am building an app that will convert swimming times from yards to meters, and can't figure out some important stuff.
I need a user to enter a time as this: minutes:seconds.hundredths
But it has to come to me in milliseconds, so that I can perform the conversion. After that I need to put it back into that format and display it to the user.
For example, if someone swam a 200 yard Freestyle in 1:52.43, I need to figure out how to multiply it by 1.11 and add 3.2 seconds, then display it to the user as their converted time for a 50 meter length pool.
If your date format is like "2011-05-31 23:59:59";
SimpleDateFormat curFormater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
java.util.Date dateObj = null;
try {
dateObj = curFormater.parse(pDate);
millisecond = dateObj.getTime();
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
For more info for Date formatting refer
http://developer.android.com/reference/java/text/SimpleDateFormat.html
http://download.oracle.com/javase/1.4.2/docs/api/java/text/SimpleDateFormat.html
http://developer.android.com/reference/java/text/SimpleDateFormat.html