We have some timestamps represented as long in millis since epoch. Within strings for logging, exceptions, or toString() methods, these timestamps need to be formatted. A simple and clean format is enough.
So, what is the simplest and fastest method for formatting a timestamp in Java?
Requirements:
input timestamps represented as long in millis since epoch
output should be a string
fast
low CG overhead
a simple and clean output is sufficient, since it is only for internal purposes (debugging and logging), e.g. something minimal: 20141220 174522.23
if possible within JDK
the time zone is the system time zone
In particular, did somebody did a benchmark of JDK methods that can be used for this?
Actually I don't want to use SimpleDateFormat, since I believe its flexibility comes with too much overhead.
Easy to use and reasonable fast:
// All Java versions:
new java.sql.Timestamp(millis).toString(); // 2016-10-29 12:28:41.979
// Recommended when using Java 8+ (about +50% faster than Timestamp), standards compliant format
// checked with jmh 1.15
java.time.Instant.ofEpochMilli(millis).toString(); // 2016-10-29T10:28:41.979Z
The fastest implementation is very likely to be:
Long.toString(millis);
If performance is the most important thing, you should use that.
Actually I don't want to use SimpleDateFormat, since I believe its flexibility comes with too much overhead.
According to a quick jmh benchmark, on my laptop, Long.toString gets twelve million ops/second and SimpleDateFormat is two million.
What's your budget? Once you know that you'll be able to decide which of those is most appropriate.
Apache Commons Lang's FastDateFormat class is absolutely a good alternative to SimpleDateFormat. It's fast and also Thread-Safe ( especially usefull in multi-threaded server environments). All patterns are compatible with SimpleDateFormat (except time zones and some year patterns).
The summary of the constructor is :
FastDateFormat(String pattern, TimeZone timeZone, Locale locale)
You could find more info at FastDateFormat
Try:
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(timeStamp);
Or:
Date date = new Date(milliseconds);
Not sure which one is faster though.
To format the Date into a string, you can use SimpleDateFormat:
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd HHmmss.SSS"); // should output something like you desired: 20141220 174522.23
String formattedDate = sdf.format(date);
Related
I have a requirement of getting UTC time , hence in many places iam using below code for calcualting utc time.
System.currentTimeMillis() ;
Iam in IST - (GMT+5:30) , System.currentTimeMillis() - should display UTC time (IST-5:30) , instead it is taking current time (GMT+5:30).
I donot want to use the Apache of joda date and time api. i want to use the Java api itslef. Help me in resolve my issue.
System.currentTimeMillis() just returns a long - that's not in any sort of date format.
If you're actually using:
Date date = new Date(System.currentTimeMillis());
System.out.println(date);
then you're just seeing the result of Date.toString(), which always uses the system default time zone.
Use DateFormat (e.g. SimpleDateFormat) to specify the calendar system (typically Gregorian), time zone and format you want to use. For example:
Date date = ...;
DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss",
Locale.US);
format.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
String result = format.format(date);
As an aside, I'd strongly recommend abstracting the idea of "getting the current time" into an interface which you implement in one case using System.currentTimeMillis() (or equivalently, just new Date()) but implement for testing purposes with a value you can set and update at will. Then inject this "clock" interface into anything which needs to access the current date/time. It makes it much easier to test time-based components.
(I'd also strongly recommend using Joda Time or the java.time package from Java 8 if you possibly can. I know you've said you don't want to, but I suspect that's because you haven't spent as much time swearing at java.util.Date and java.util.Calendar as some of us. Both of those alternatives will lead to much cleaner code which is much easier to read and reason about. If you're trying to avoid a one-time hit of getting Joda Time into your build process, weigh that against the amount of time you're likely to spend maintaining your code. Or just update to Java 8... Java 7 will be out of free-update support soon anyway...)
In some system I have to operate on dates which may have limited precission (like month and year only or year only), e.g. "2001" or "January 2011". I need to know not only date, but the presission (day, month or year) as well.
I can do this by hand, but does anybody know any java library which supports this type of dates with variable precission?
I would consider using a well known library such as Joda Time and model each "date" as a time span (Interval in Joda Time).
After all, that's sort of what it is; "2001" is not actually a specific point in time, but a period.
The span / length of the interval would reveal the precision, and the starting point of the period could be interpreted as the point in time at which the "date occurred".
Lookup SimpleDateFormat and Date. These both classes should be sufficient for your use case.
Reference: SimpleDateFormat
why not use the Calendar class ?
Use Joda Time which already has support for a YearMonth type (amongst other things) - you can create your own Year type if you want, based on similar code.
Well aware of performance and thread issues with SimpleDateFormat, I decided to go with FastDateFormat, until I realized that FastDateFormat is for formatting only, no parsing!
Is there an alternative to FastDateFormat, that is ready to use out of the box and much faster than SimpleDateFormat?
I believe FastDateFormat is one of the faster ones, so anything that is about as fast would do.
Just curious , any idea why FastDateFormat does not support parsing? Doesn't it seriously limit its use?
Note that since commons-lang 3.2, FastDateFormat supports parsing as well as printing.
See: http://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/time/FastDateFormat.html
At a best guess, it's to keep FastDateFormat... well... fast, by limiting it to display only.
Apache Commons DateUtils has a parseDate function, but that uses SimpleDateFormat internally.
An alternative is to use the JodaTime library. It's a complete replacement for dealing with DateFormat, Date, and Calendar objects.
JodaTime has a DateTimeFormatter that can be used to create DateTime objects (JodaTime's equivalent of Java's Date objects) from strings.
An example of how to use it is like this:
String strInputDateTime = "2010-12-27"; // An example, this would really come from outside
DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM-dd");
DateTime dt = fmt.parseDateTime(strInputDateTime);
I don't know if this is really any faster than SimpleDateFormat, though.
Found something interesting here of this case in Android:
http://andmob.wikidot.com/faq-simpletimeformat
SimpleDateFormat, the first time you
try parsing (or, presumably,
formatting) a date, will load in all
the timezone data for your locale.
This will take 2-3 seconds. It is
hoped that this will be fixed in some
future edition of Android.
In the interim, consider using
AsyncTask to "warm up"
SimpleDateFormat in your process
before you need it. Just parse some
date in the AsyncTask doInBackground()
to get it to load the timezones
sometime when it will not impact the
user so much. Once initialized in your
process, SimpleDateFormat will run
quickly until your process is
terminated.
As of Java 8, one can use DateTimeFormatter along with the the Java 8 Time API to both parse and format dates. From the documentation:
This class is immutable and thread-safe.
It's recommended to use this class if possible for new work going forward instead of using SimpleDateFormat.
The 'problem' with SimpleDateFormat is not performance, its thread safety.
If you have thousands of threads and synchronizing is not an issue use synchronized (you can also pool the instances to alleviate this a little)
If you have a reasonable amount of threads the recommended way is to have a separate instance for each SimpleDateFormat.
UPDATE
As of Java 8, just use DateTimeFormatter. It is immutable, thread safe, faster, and more flexible. (It also offers nice features like default patterns for ISO-8601 date/time strings.)
Do you really need to parse dates that quickly? Have you tested SimpleDateFormat and found it too slow for your needs?
Note, there are a variety of ways to cache slow-to-construct, non-thread-safe class instances (e.g. ThreadLocal, pools).
I want to save a Date object to a readable string (for example 22/10/2009 21:13:14) that is also parsable back to a Date object.
I have tried many things and the best I could find was to use DateFormater for parsing and formating but it has a setback. When you format a date you lose seconds information. I tried to find if there is an option to format it and display the seconds (even better would be to the millisecond level since that's the resolution the Date object allows you to have) but I came up short.
Any ideas?
Take a look at java.text.SimpleDateFormat
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss.SSS");
Date dt = new Date();
String S = sdf.format(dt); // formats to 09/23/2009 13:53:28.238
Date dt2 = sdf.parse(S); // parses back
SimpleDateFormat can format and parse a date based on a very simple pattern system that include second and even milliseconds.
Other answers are all good.
But when doing this kind of thing please pick a format that sorts properly when coded as a string.... "yyyy/MM/dd HH:mm:ss" is fine. It always astounds me when software engineers pick a date format which doesn't sort in the obvious, convenient way.
You'll save your fellow developers a lot of pain at some distant point in the future - think of it as good karma :-)
ISO 8601
Use ISO 8601 format.
It’s flexible, it includes seconds and fraction of second if there are any, but you may also leave them out if they are 0.
It’s standard, so more and more tools format and parse it. Great for serialization for storage or data interchange.
It goes like 2009-10-22T21:13:14, I should say it’s pretty human-readable (though the T in the middle that denotes the start of the time part may feel unusual at first).
The strings sort properly, as mikera requested in another answer, as long as the years are in the four-digit range from 1000 through 9999.
The classes of java.time, the modern Java date and time API, as well as those of Joda Time parse ISO 8601 as their default, that is, without any explicit formatter, and produce the same format from their toString methods.
A modest demonstration of using java.time:
LocalDateTime dateTime = LocalDateTime.of(2009, 10, 22, 21, 13, 14);
String readableString = dateTime.toString();
System.out.println(readableString);
LocalDateTime parsedBack = LocalDateTime.parse(readableString);
System.out.println(parsedBack);
This prints two identical lines:
2009-10-22T21:13:14
2009-10-22T21:13:14
The latter System.out.println() call implicitly calls toString() once more, so this shouldn’t surprise.
A little off-topic, but I always feel the need to remind people that DateFormat and SimpleDateFormat are not thread safe! The Sun documentation clearly states this, but I keep finding code out in the wild where people stick a SimpleDateFormat in a static ...
If you want to do it a little simpler, and be spared from making your own DateFormat that most other Answers involve, you can leverage the default format in java.time.Instant:
(new Date()).toInstant.toString();
Is there a way to format a UTC time into any arbitrary string format I want in java? Basically I was thinking of having some class take the timestamp and I pass it is string telling it how I want it formated, and it returns the formatted string for me. Is there a way to do this?
The java.text.SimpleDateFormat class provides formatting and parsing for dates in a locale-sensitive manner.
The javadoc header for SimpleDateFormat is a good source of detailed information. There is also a Java Tutorial with example usages.
The DateFormat class or SimpleDateFormat should get you there. For example, http://www.epochconverter.com/ lists the following example to convert a epoch time to human readable timestamp with Java:
String date = new java.text.SimpleDateFormat("dd/MM/yyyy HH:mm:ss").format(new java.util.Date (epoch*1000));
Date instances are insufficient for some purposes.
Use Joda Time instead.
Joda time integrates with Hibernate and other databases.
One gotcha to be aware of is that SimpleDateFormat is NOT thread-safe. Do not put it in a static field and use it from multiple threads concurrently.