Given a method that needs to use the values of the current day/month/year on every invocation and which is invoked several (millions or more) times per second, is there any faster way of implementing that functionality, other than creating a Calendar object for the current time on every invocation?
Using Calendar.getInstance() or calendar.setTime() (with time field recalculation) is overly expensive to do many times per second.
Standard Java solutions are preferable (e.g., over using third party libraries).
To get the current date/time, I find that LocalDate.now() is faster than Calendar.getInstance(). The LocalDate class can be found in the java.time package, which is new since Java 8 (Of course, if you want to maintain compatibility with old Java versions, that may not be an option).
The best solution within the scope of standard java (no 3rd party-libraries) is using the class LocalDate. So far this answer is identical to that of #Chronio, but I differ in use. The factory method now() cannot be so quick because it exploits the system timezone - maybe even using a synchronized approach anywhere in the depth of TimeZone.getDefault().
But the class LocalDate is very quick if you use its factory methods with arguments of year, month and day-of-month. Here you are just setting the state members without any timezone calculation and without any calculation of gregorian calendar math (okay only quick year-dependent length-of-month-check is involved). Just see the source code.
use the Date, instead of Calendar class it will give you the current date
Related
The set of date and time functions I need are pretty basic.
An object to represent a date/time (for convenience in function calls).
Conversion functions to and from y,m,d,h,m,s.
Format/parse functions to and from numeric-only localised string representation. Eg dd/mm/yyyy, yyyy-mm-dd, mm.dd.yyyy or whatever order and delimiters are locally expected.
A system function to get the current local date and time (timezones not required).
Compatible with the DatePicker widget.
Thread safe. Static functions available to both UI and worker (NDK) threads.
So far I've found that:
Calendar and GregorianCalendar can do the conversions, but they're clunky to use and they're not thread safe.
SimpleDateFormat can do the formatting, if I could only figure out which magic string to feed it! The default is not numeric.
Time has a nicer set of conversion functions, but has no date/time object and the parse/format functions are documented only indirectly. And it smells a lot more like Unix than Java.
So do I find a way to fix the thread safety and try to persuade SimpleDateFormat to give me what I need? Or do I give up and jump ship to Time? Or have I missed something?
Just to be clear, this is not a request for a library recommendation or a shopping list. It's a request for assistance on how to implement a specific set of functions using the given Android API. I'm looking for an expert on using these libraries to point out a path through the morass. I would hope that a well-written answer would benefit other readers also struggling with this part of Android.
Personally I find Joda-Time to be able to handle almost everything you need for date and time. Since it's just a .jar it should be able to be imported.
Here's how to use it, for the questions you asked specifically:
An object to represent a date/time - DateTime for immutable or MutableDateTime for one that you need to apply transformations to.
These objects have many methods for conversion, see the Joda-Time API for AbstractDateTime as an example, as all of Joda's classes extend AbstractDateTime
You can use String convertedToString = new DateTime().toString("yyyy-MM-dd") to get it as 2014-05-05. To reverse this, use this API: DateTimeFormatter parseDateTime(someStringThatRepresentsADate)
DateTime now = new DateTime() gives you now, as a DateTime object
You can get a DateTime object from several other classes, such as Calendar by doing something like DateTime fromCalendar = new DateTime(myCalendarObject)
See The FAQ for Joda on multi-threading
In order to import Joda into your Android project, assuming you're using Android studio and Gradle, see this answer: Android Studio: Add jar as library?
The documentation for Date.getTimezoneOffset says:
Deprecated. As of JDK version 1.1, replaced by
-(Calendar.get(Calendar.ZONE_OFFSET) + Calendar.get(Calendar.DST_OFFSET)) / (60 * 1000).
Why was it deprecated? Is there a shorter way (Apache Commons?) to get the offset from UTC in hours/minutes? I have a Date object ... should I convert it to JodaDate for this?
And before you ask why I want the UTC offset - it's just to log it, nothing more.
There are 2 questions here.
Why was Date.getTimezoneOffset deprecated?
I think it is because they actually deprecated nearly all methods of Date and moved their logic to calendar. We are expected to use generic set and get with the parameter that says which specific field we need. This approach has some advantages: less number of methods and the ability to run setters in a loop passing a different field each time. I personally used this technique a lot: it makes code shorter and easier to maintain.
Shortcut? But what's wrong with call
Calendar.get(Calendar.DST_OFFSET) comparing to
Calendar.getTimeZoneOffset()
As far as I can see the difference is 6 characters.
Joda is a very strong library and if you really have to write a lot of sophisticated date manipulation code switch to it. I personally use the standard java.util.Calendar and don't see any reason to use external libraries: good old calendar is good enough for me.
All of the date manipulation logic was moved out of Date once the Java implementers realized that it might need to be implemented differently for different types of calendars (hence the need to use a GregorianCalendar to retrieve this info now). A Date is now just a wrapper around a UTC time value.
Take care before you paste code from this page.
Perhaps just me but I believe that in order to get the tz offset in minutes you need to do
int tzOffsetMin = (cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET))/(1000*60);
rather than what the Javadoc says, which is:
int tzOffsetMin = -(cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET))/(1000*60);
Calendar.ZONE_OFFSET gives you the standard offset (in msecs) from UTC. This doesn't change with DST. For example for US East Coast timezone this field will always be -6 hours regardless of DST.
Calendar.DST_OFFSET gives you the current DST offset (in msecs) - if any. For example during summer in a country that uses DST this field is likely to have the value +1 hour (1000*60*60 msecs).
I have a simple java object with several date properties and I always seem to change my mind on how to define them. Should the properties be defined as date objects or strings? The object is going to be used in struts 1.3 application with iBatis as the persistence layer and mysql as the database. The database columns are defined as datetime and they can possibly be null and I usually don’t care about the time portion.
public Date getForcastDate();
or
public String getForcastDate();
Most of the existing code base uses strings, but that just doesn’t seem quite right to me.
Keep your dates as Dates. That way you can change formatting depending on locales, check for invalid dates, sort by them etc.
By keeping them as strings you're potentially throwing away data (e.g. milliseconds if your formatter doesn't use them) and definitely behaviour.
Using strong-typing (e.g. keeping them as Dates) will aid in terms of development. Your method signatures become clearer, refactoring using IDE tooling becomes easier etc. Otherwise you end up with APIs that talk in nothing but strings, it's trivial to mix up parameters, and it becomes impossible to work out what's going on.
Tip: Check out Joda-Time as a better alternative to the standard java.util.Date.
I would use Date object because it cleaner to store a Date and convert it to a String when needed. Otherwise you have to hard code a formatted date into a String field.
I would never use Strings in this cas as what would today be 8/3/11 or 3/8/11 or 2011-03-08. This is really a specific case of trying to use the most restrictive type/class possible for a variable. This is so that you can understand its behaviour more fully, both by having a restricted or specialised set of methods and by helping documentation of other classes using it. Using a Date here would allow you to use a Calendar object to add days or months. Conversion to or from a string only needs to be done for input and output.
In practice if they were only dates I would crete my own Date class so could ignore times or use JodaTime which provides easier manipulation than the java Date
In my code I always use the most high level object. In this case I would suggest - Calendar. Here is separate discussion about Date and Calendar. I always think this way - converting Calendar/Date to String is simple - use SimpleDateFormatter. But very often you will need to do something with the date (add several days or hours, subtract a year, handle timezones etc) and then each time you would have to convert it from String to Calendar/Date.
Date if you had to, but java.util.Calendar would probably be more appropriate nowadays. With a String you'd have to worry about format like #jzd mentioned. With Calendar, you can easily switch between formats. Also Calendar lets you get at the date with Calendar.getTime()
Previously, when I first design a stock application related software, I decide to use java.util.Date to represent date/time information of a stock.
Later, I realize most of the methods in java.util.Date is deprecated. Hence, very soon, I refactor all my code to make use of java.util.Calendar
However, there is 2 shortcomings I encounter.
Construct java.util.Calendar is comparative slower than java.util.Date
Within the accessors getCalendar method of Stock class, I need to clone a copy, as Calendar is a mutable class
Here is the current source code for Stock.java
Recently, I discover Joda-Time. I do the following benchmarking, by creating 1,000,000 java.util.Date, java.util.Calendar and org.joda.time.DateTime. I found org.joda.time.DateTime performs better than java.util.Calendar, during instantiation.
Here is the benchmarking result.
This instantiation speed is important, especially many instance of Stocks will be created, to represent a long price history of a stock.
Do you think is it worth to migrate from Java Calendar to Joda Date Time, to gain application speed performance? Is there any trap I need to pay attention to?
Note that java.util.Date is mutable too - so if it's a problem now you're using Calendar, it would have been a problem using Date too. That said, using Joda Time is definitely worth doing just because it's a much, much better API.
How certain are you that performance is actually an issue in your particular app? You say there will be "many instances" of Stock created... how many? Have you profiled it? I wouldn't expect it to actually make a significant difference in most situations. It's not obvious from your benchmarking graph what you're actually measuring.
Moving to Joda Time is a good idea in general, but I would measure the performance to see how much difference it really makes for you.
Why do you need a Calendar in your Stock class? I think using a Date to represent a point in time is fine. This seems to be what you want, because you want the Calendar object in the a stock to be immutable, which the Date class should be, if you ignore the deprecated methods.
You can use a temporary Calendar when you need to do time operations on a Date outside the Stock class:
Calendar calendar = Calendar.getInstance();
calendar.setTime(stock.getDate());
System.out.println(calendar.getYear());
Like this you can still store a Date in your Stock class, which should have the best performance when only store and retrieve Stock objects from a data storage. If you do several operations at once you can also reuse the same Calendar object.
If you don't like the Calendar interface you could still use Joda Time to do the time operations. You can probably convert dates to and from Joda Time if needed, to do time operations, and still store Date objects in your Stock class.
If java.util.Calendar instances to be replaced with org.joda.time.DateTime are parsed and/or formatted to a particular pattern, e.g.
String format = "YYYY-MM-dd HH:mm:ss";
Within method signatures for parameter and return types, as well as variable declarations
and instantiations, repace whole word occurrences of the class names Calendar (with
DateTime) and SimpleDateFormat (with DateTimeFormatter), respectively
Replace the formatter instantiation statement, e.g.
formatter = new SimpleDateFormat(format);
with
formatter = DateTimeFormat.forPattern(format);
Replace calls to methods of `SimpleDateFormat', e.g.
String dateStr = formatter.format(Calendar.getInstance().getTime());
with
String dateStr = DateTime.now().toString(formatter);
and
formatter.parse(dateStr);
with
DateTime.parse(dateStr, formatter);
I used Joda in the past, and it is an awesome library.
In terms of performance, you'll have to test it, unfortunately. But refactoring your code seems too much. Personally, I used Date throughout my whole application (including DB store and retrieve), and used Joda only when I needed data manipulation. Joda calculates fields only when needed, so I guess the overhead will be much lower than using Java API classes; furthermore, you won't have object version issues to transfer and handle Date objects in your DB, serialize objects and such. I don't expect Joda to break such compatibility, but it is less likely using Date.
It is always better to move to joda-time in general. But it it is really worth to move to the joda-time for your project is based on your use-cases pertaining to the date usage. Look at slide number 46 in the presentation for performance related numbers for some of the operationslink text
When you look at the javadoc of the java.util.Date class, most of the methods are deprecated. Why was this done?
Well, for two related reasons. It was a very poor implementation of the concept of Dates and Times and it was replaced by the Calendar class.
The Calendar class, although an improvement, leaves a lot to be desired as well, so for serious Date/Time work, everyone recommends Joda-Time. Java 8 brings the new java.time.* package, inspired by Joda-Time, defined by JSR-310, and intended to supplant the old Date/Calendar classes.
Edit: In response to the specific question of why the implementation is poor, there are many reasons. The JavaDoc sums it up as follows:
Unfortunately, the API for these functions was not amenable to internationalization.
In addition to this general deficiency (which covers issues like the lack of a Time Zone component as well as the date formatting which is better handled in DateFormat and the inability to have a non-Gregorian calendar representation), there are specific issues which really hurt the Date class, including the fact that year is presented in an offset of 1900 from Common Era year.
Calendar has its own problems, but even as early as JDK 1.1 it was obvious that java.util.Date was not going to cut it. Even though Calendar is arguable the worst JDK API, it has taken until version 7 to attempt to address it.
Date is mutable
Date doesn't have support for time zones
The latter led to it being replaced by Calendar. And the former, combined with the ease-of-use, lead to both being replaced by Joda-Time / JSR-310 (java.time.* package)
They're deprecated because Date was written as fast as possible back in the day when they wanted to rush the JDK out the door.
It turns out the Dates and Calendars are Hard. So, they created the Calendar class, which much more thought, in order to handle the Hard Parts of working with calendars.
They deprecated the Date methods and delegated to Calendar because they didn't want to change the behavior of the existing Date methods, and possibly break existing applications.
Here's a good answer straight from Oracle: http://www.oracle.com/technetwork/articles/java/jf14-date-time-2125367.html
A long-standing bugbear of Java developers has been the inadequate support for the date and time use cases of ordinary developers.
For example, the existing classes (such as java.util.Date and SimpleDateFormatter) aren’t thread-safe, leading to potential concurrency issues for users—not something the average developer would expect to deal with when writing date-handling code.
Some of the date and time classes also exhibit quite poor API design. For example, years in java.util.Date start at 1900, months start at 1, and days start at 0—not very intuitive.
... java.util.Date represents an instant on the timeline—a wrapper around the number of milli-seconds since the UNIX epoch—but if you call toString(), the result suggests that it has a time zone, causing confusion among developers.
I don't know the official reason why it has been deprecated, but as far as I can tell GregorianCalendarand Joda-Time support operations on dates, meaning that you can add, for instance, a day to a date and have its month and year updated accordingly.
For instance, say you want to compute the day after the current date and today is May 31st; with java.util.Date, you just have getDays() +1, which returns 32, and you have to handle the knowledge that the current month doesn't have 32 days by yourself; with GregorianCalendaror Joda.time, adding a day to May 31st results in an object representing June 1st, hiding the complexity from your sight.