What's wrong with time subtraction? - java

I know that Date class can be really painful at times.
Could you please give me some painkillers in the form of the piece of advice on how to subtract time?
What I have is:
SimpleDateFormat format = new SimpleDateFormat("dd.MM.yyyy HH:mm");
SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
String s = "13.04.2015 16:00";
String s2 = "13.04.2015 15:30";
Date date = format.parse(s);
System.out.println(timeFormat.format(date.getTime() - format.parse(s2).getTime()));
This gives me 02:30:00, but I'd love to get 00:30:00 :)

I suggest to force common TimeZone for both SimpleDateFormat:
format.setTimeZone(TimeZone.getTimeZone("UTC"));
timeFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
before formatting date.

I'm not sure if you are stuck to Java Date class by some requirements, but if you are working with date and time a lot in your application I recommend Joda-Time library. It solves many problems out of the box and allows executing operations on date and time in easier way.

Related

Wrong Date inserted in Date column

I have a strange situation.
In my application we are inserting a record with the current date (MM/dd/yyyy) when users access something in the application.
Sometimes the date is getting inserted with a wrong value that isn't the current date. (Ie: '21/09/2014', '13/09/2180', '22/08/2179'). We are using JPA to insert the record from JAVA. Please help me to find out the issue or solution for this.
Below is the code, where I am preparing/passing the value for Domain object.
Date curDate = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
UserAccessObj.setAccessedDate(sdf.parse( sdf.format( curDate ) ));
Here setAccessedDate(Date) is java.util.Date setter method in domain object.
So, what might be the issue? I am not able to trace the issue.
Instead of this:
UserAccessObj.setAccessedDate(sdf.parse(sdf.format(curDate)));
Try this:
UserAccessObj.setAccessedDate(curDate);
Is
sdf.parse( sdf.format( curDate ) )
strictly necessary ? You're taking a date, converting it to a string, and then parsing it as a date ? I suspect you're doing this to get rid of the time component of the (misleadingly-named) Date object ? I think using the Calendar class as per the answer in this thread is faster/safer. The best answer is to use the Joda-Time API.
I don't know if it's causing your problem, but it's adding unnecessary complexity. Note also that SimpleDateFormat is not thread-safe, and if the above code shares an instance of a SimpleDateFormat that would definitely account for peculiar behaviour. Again, Joda-Time provides thread-safety in this domain.
I think you can do is use Calendar object to get the current system time
Calendar cal = Calendar.getInstance();
and then convert it into the SimpleDateFormat.
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
dateFormat.format(cal.getTime());
and then you have your own code
UserAccessObj.setAccessedDate(sdf.parse( sdf.format( curDate ) ));
Hope it helps :)
Save the input date into DB in this format : "yyyy-MM-dd". Correct date will be saved.

Iterate through date ranges without using libraries - Java

Hi I want to iterate through a date range without using any libraries. I want to start on 18/01/2005(want to format it to yyyy/M/d) and iterate in day intervals until the current date. I have formatted the start date, but I dont know how I can add it to a calendar object and iterate. I was wondering if anyone can help. Thanks
String newstr = "2005/01/18";
SimpleDateFormat format1 = new SimpleDateFormat("yyyy/M/d");
Date date = format1.parse(newstr);
Calendar calendar = new GregorianCalendar();
calendar.setTime(date);
while (someCondition(calendar)) {
doSomethingWithTheCalendar(calendar);
calendar.add(Calendar.DATE, 1);
}
Use SimpleDateFormat to parse a string into a Date object or format a Date object into a string.
Use class Calendar for date arithmetic. It has an add method to advance the calendar, for example with a day.
See the API documentation of the classes mentioned above.
Alternatively, use the Joda Time library, which makes these things easier. (The Date and Calendar classes in the standard Java API have a number of design issues and are not as powerful as Joda Time).

Getting the exact time and date for my log track

Good day Lovely people
Please help a brother out. Well I'm a master in visual basic but in java let me rather not say.
In VB here are my methods:
System.DateTime.Now.ToLongTimeString()
System.DateTime.Now.ToString() + "/" + System.DateTime.Now.Month.ToString() + "/" + System.DateTime.Now.Year.ToString()
The first method will return the exact time e.g = 12:08:36 AM
And the second method will return the exact date e.g = 2012/09/26
I want to get the very same results but using java.How do i go about doing that.
Oooh Thanks in advance.
In .NET, DateTime.Now gives you the local date and time, in your local time zone.
If you use new Date() or the like in Java, it will give you a value which has no awareness of time zones. To take time zones into account, you should either create a Calendar which has the right time zone, or if you want to create an appropriate string you should use SimpleDateFormat - again, set to the right time zone before formatting. For example:
SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd", Locale.US);
format.setTimeZone(...); // Whichever time zone you want
String text = format.format(new Date()); // "now"
Also note that Joda Time is a much better Java API for date/time than the built-in Calendar and Date classes.
Finally, your second piece of sample code in .NET is buggy - you should only evaluate DateTime.Now once; ideally just passing in a format string e.g. DateTime.Now.ToString("yyyy/MM/dd"). Even if you want to convert each bit to a string separately, however, you fetch the value once to a local variable and then reuse it. Otherwise, if you execute that code around midnight, the date can change - so for example, if you executed it just before the start of 2013, you could end up with a string of "2012/12/1" or "2012/1/1" neither of which would be correct.
Use java.text.SimpleDateFormat class to format date and new java.util.Date() will create an instance system date default.
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
SimpleDateFormat dateFormat1 = new SimpleDateFormat("hh:mm:ss a");
System.out.println(dateFormat.format(new Date)); //2012/09/26
System.out.println(dateFormat1.format(new Date)); //12:08:36 AM
To get the object representing the current date, you can use just new Date(), to format it, use SimpleDateFormat.

java/android datetime timespan

If i have a simpledateformat object:
SimpleDateFormat format = new SimpleDateFormat("HH:mm");
And have two times, 12:12 and 13:13 for example, is there an easy way to check if the current time is between the two SimpleDateFormats (The clock is 12:15 for example)? Thanks
DateFormat newDateFormat = new SimpleDateFormat("HH:mm");
Date d1 = newDateFormat.parse("12:12");
Date d2 = newDateFormat.parse("13:13");
Date myDate = newDateFormat.parse("12:15");
if(myDate.getTime() >= d1.getTime() && myDate.getTime() <= d2.getTime()){
//yes it is in between including border
}
Compare them using Date or Calendar objects, SimpleDateFormat is just a representation. You can use format.parse("12:12") and ir returns a Date object representing that time.
If anyone is looking for a better and lighter library to use in Android/ Java that handles interval better, you can use a library that a wrote to use in my own Android app. https://github.com/ashokgelal/samaya
Also, see this question: Do we have a TimeSpan sort of class in Java

Convert Java Date into XML Date Format (and vice versa)

Is there a nice and easy way to convert a Java Date into XML date string format and vice versa?
Cheers,
Andez
Original answer
I am guessing here that by "XML Date Format" you mean something like "2010-11-04T19:14Z". It is actually ISO 8601 format.
You can convert it using SimpleDateFormat, as others suggested, FastDateFormat or using Joda Time which was I believe especially created for this purpose.
Edit: code samples and more
As earnshae stated in a comment, this answer could be improved with examples.
First, we have to make clear that the original answer is pretty outdated. It's because Java 8 introduced the classes to manipulate date and time - java.time package should be of interest. If you are lucky enough to be using Java 8, you should use one of them. However, these things are surprisingly difficult to get right.
LocalDate(Time) that isn't
Consider this example:
LocalDateTime dateTime = LocalDateTime.parse("2016-03-23T18:21");
System.out.println(dateTime); // 2016-03-23T18:21
At first it may seem that what we're using here is a local (to the user date and time). However, if you dare to ask, you'll get different result:
System.out.println(dateTime.getChronology()); // ISO
This actually, the ISO time. I believe it should read 'UTC' but nonetheless this has no notion of local time zone. So we should consider it universal.
Please notice, that there is no "Z" at the end of the string we are parsing. Should you add anything apart of date and time, you'll be greeted with java.time.format.DateTimeParseException. So it seems that this class is of no use if we want to parse ISO8601 string.
ZonedDateTime to the rescue
Fortunately, there is a class that allows for parsing ISO8601 strings - it's a java.time.ZonedDateTime.
ZonedDateTime zonedDateTime = ZonedDateTime.parse("2016-03-23T18:21+01:00");
System.out.println(zonedDateTime); // 2016-03-23T18:21+01:00
ZonedDateTime zonedDateTimeZulu = ZonedDateTime.parse("2016-03-23T18:21Z");
System.out.println(zonedDateTimeZulu); // 2016-03-23T18:21Z
The only problem here is, you actually need to use time zone designation. Trying to parse raw date time (i.e. "2016-03-23T18:21") will result in already mentioned RuntimeException. Depending on the situation you'd have to choose between LocalDateTime and ZonedDateTime.
Of course you can easily convert between those two, so it should not be a problem:
System.out.println(zonedDateTimeZulu.toLocalDateTime()); // 2016-03-23T18:21
// Zone conversion
ZonedDateTime cetDateTime = zonedDateTimeZulu.toLocalDateTime()
.atZone(ZoneId.of("CET"));
System.out.println(cetDateTime); // 2016-03-23T18:21+01:00[CET]
I recommend using this classes nowadays. However, if your job description includes archeology (meaning you are not lucky enough to be working with more than 2 year old Java 8...), you may need to use something else.
The joy of SimpleDateFormat
I am not a very big fan of https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html, but sometimes you just have no other choice. Problem is, it is not thread-safe and it will throw a checked Exception (namely ParseException) in your face if it dislikes something. Therefore the code snippet is rather ugly:
private Object lock = new Object();
// ...
try {
synchronized (lock) {
// Either "2016-03-23T18:21+01:00" or "2016-03-23T18:21Z"
// will be correctly parsed (mind the different meaning though)
Date date = dateFormat.parse("2016-03-23T18:21Z");
System.out.println(date); // Wed Mar 23 19:21:00 CET 2016
}
} catch (ParseException e) {
LOG.error("Date time parsing exception", e);
}
FastDateFormat
FastDateFormat is synchronized, therefore you can at least get rid of the synchronized block. However, it is an external dependency. But since it's the Apache Commons Lang and it is thoroughly used, I guess it is acceptable. It is actually very similar in usage to SimpleDateFormat:
FastDateFormat fastDateFormat = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mmX");
try {
Date fastDate = fastDateFormat.parse("2016-03-23T18:21+01:00");
System.out.println(fastDate);
} catch (ParseException e) {
LOG.error("Date time parsing exception", e);
}
JodaTime
With Joda-Time you may think that following works:
DateTimeFormatter parser = ISODateTimeFormat.dateTimeParser();
LocalDateTime dateTime = LocalDateTime.parse("2016-03-23T20:48+01:00", parser);
System.out.println(dateTime); // 2016-03-23T20:48:00.000
Unfortunately, no matter what you put at last position (Z, +03:00, ...) the result will be the same. Clearly, it isn't working.
Well, you really should be parsing it directly:
DateTimeFormatter parser = ISODateTimeFormat.dateTimeParser();
DateTime dateTime = parser.parseDateTime("2016-03-23T21:12:23+04:00");
System.out.println(dateTime); // 2016-03-23T18:12:23.000+01:00
Now it will be OK. Please note, that unlike one of other answers, I used dateTimeParser() and not dateTime(). I noticed subtle, but important difference in behavior between them (Joda-Time 2.9.2). But, I leave it to the reader to test it and confirm.
As already suggested use SimpleDateFormat.
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
String date = sdf.format(new Date());
System.out.println(date);
Date d = sdf.parse(date);
My guess is that the format/pattern that your looking for is yyyy-MM-dd'T'HH:mm:ss
Also have a look at http://www.w3schools.com/schema/schema_dtypes_date.asp
Using Joda Time you would do the following:
DateTimeFormatter fmt = ISODateTimeFormat.dateTime(); // ISO8601 (XML) Date/time
DateTime dt = fmt.parseDateTime("2000-01-01T12:00:00+100"); // +1hr time zone
System.out.println(fmt.print(dt)); // Prints in ISO8601 format
Thread safe, immutable and simple.
The Perfect method, use XMLGregorianCalendar:
GregorianCalendar calendar = new GregorianCalendar();
calendar.setTime(v);
DatatypeFactory df = DatatypeFactory.newInstance();
XMLGregorianCalendar dateTime = df.newXMLGregorianCalendar(calendar);
return dateTime.toString();
Just by using SimpleDateFormat in java we can do this...
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
Date date = sdf.parse("2011-12-31T15:05:50+1000");
I would recommend to use the java built in class javax.xml.bind.DatatypeConverter. It can handle conversion to and from most of the xml simple types. It is a little bit cumbersome for dates that you have to go through a Calendar object but on the other hand it handles all variants of zone information that can occur in a xml datetime field.
From xml:
Calendar c = DatatypeConverter.parseDateTime("2015-10-21T13:25");
Date d = c.getTime();
To xml:
Date yourDate = new Date()
Calendar c = Calendar.getInstance();
c.setTime(yourDate);
String xmlDateTime = DatatypeConverter.printDateTime(c);
EDIT
The DatatypeConverter class is no longer publicly visible in Java 9 and above since it belongs to the javax.xml.bind package. See this question for more information and possible solutions. The solution proposed by loic vaugeois to use XmlGregorianCalendar is much better in this case.
You can parse and format dates to and from any format using SimpleDateFormat
To comply with ISO8601, the timezone must be in the format +HH:MM or - HH:MM
With Simpledateformat you must use XXX instead of Z (see NovelGuy answer)
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
Without knowing exactly what format you need, the generic response is: you're going to want DateFormat or SimpleDateFormat. There is a nice tutorial on both here.

Categories

Resources