How to convert ZonedDateTime/OffsetDateTime to Date using ThreeTenABP? - java

Using the ThreeTen Android Backport library, what is the simplest way to convert a ZonedDateTime or OffsetDateTime into an old-school java.util.Date instance?
If I had full Java 8 libs at my disposal, this of course would be the way to do it (as in this question):
Date.from(zonedDateTime.toInstant());
But I cannot use that on Android; specifically Date.from(Instant instant) is missing.

Well, one straightforward way is to get milliseconds since epoch and create the Date from that:
long epochMilli = zonedDateTime.toInstant().toEpochMilli();
Date date = new Date(epochMilli);
Feel free to point out if there's some preferable way.

See DateTimeUtils which handles the methods added to classes like java.util.Date:
http://www.threeten.org/threetenbp/apidocs/org/threeten/bp/DateTimeUtils.html
Edit: using that, the complete code would be:
DateTimeUtils.toDate(zonedDateTime.toInstant())

Related

java-joda datetime classes (current system time)?

I'm "Converting" some c# code to java and I've come to a point where things get weird.
I'm using the joda LocalTime object as I'm dealing with time comparison only.
In c# to get the current system time we use the following code:
DateTime.Now.TimeOfDay //returns Timespan as wanted
But in Java-joda I can't find such thing and I'm forced to the following:
LocalTime nowLocalTime=new LocalTime();
LocalTime currenTime=new LocalTime(nowLocalTime.getHourOfDay(),nowLocalTime.getMinuteOfHour(),00);
Is there an alternative to that, a much sweeter way to do this? (I must pack it into LocalTime to make the use of the .Compare method).
You're looking for LocalTime.now()

Which Android APIs to use for simple date and time functions

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?

Is there any field converter for java.util.Date?

I would like to use a Date field in my playOrm mapping. However, if I use
private Date birthDate;
in my bean, it gives me an exception saying this type is not supported.
I can add Date if you open an issue. I was thinking of actually throwing an exception when people use Date that says this though instead..
Please use LocalDate, LocalTime or LocalDateTime from joda-time which
was supposed to be added in jdk7 but more than likely will end up in
jdk8. The reason for this is java.util.Date and Calendar from java
are buggy and have lots of known bugs in the jdk bug system.
See this as well
Joda Time to be included in Java 7?
If however, you still want to use Date, here is how
Map<Class, Converter> converters = new HashMap<Class, Converter>();
Converter d = new DateConverter();
converters.put(Date.class, d);
Then you need to implement the Converter interface with your DateConverter class and implement the byte[] to Date and Date to byte[] and String to Date and Date to String methods. NOTE: These methods are all called for S-SQL and for converting entities...it all uses the same converters.
The string conversions are VERY important as the command line tool will use them to convert your command line S-SQL to query the objects.
HOWEVER, if you want it built-in to PlayOrm, just open an issue and I can do it pretty quickly BUT I still suggest you use LocalDateTime instead in joda-time as it is more reliable and you can do more with it....after using joda-time quite a bit, it is on-par with C# date apis and way better than the old java stuff.
Dean
I'm not sure what you're asking for, but as stated in the Java API for Date, "As of JDK 1.1, the Calendar class should be used to convert between dates and time fields and the DateFormat class should be used to format and parse date strings. The corresponding methods in Date are deprecated."

How to use java.util.Calendar in GWT

I have to use java.util.Calendar in GWT entry point, but I got error while running the application, that is because GWT is not able to find source code, is there anyway I could fix this issue.
Thanks in advance!!!
java.util.Calendar is not an emulated class. You can find a list of emulated classes here:
http://code.google.com/webtoolkit/doc/latest/RefJreEmulation.html
I would strongly advise not to use any date/calendar library on the client side. You will probably only get yourself into trouble. In fact, even though java.sql.Date and java.util.Date are emulated in GWT, I would not use these either. If you're looking to use Calendar, then chances are you want to support timezones on the client. Using the emulated Date classes, you will somehow have to convert the client's Date from the browser's timezone to some target timezone (GMT or whatever the user defined in user preferences?). This will most definitely be error prone. Using GWT's TimeZone adds other issues. For instance, how do you map between java TimeZones and GWT TimeZones?
I recommend doing all date manipulation AND formatting on the server. On the client, you can simply use a date/month/year triplet. The server can have an association between user (or organization) and java.util.TimeZone (or joda timezone). Using the triplet and timezone you can easily create the specific instance in time.
You may be able to use com.google.gwt.user.datepicker.client.CalendarUtil.
No there is no way to use the java.util.Calendar in GWT because there is no equivalent in JavaScript. But there is an accepted feature request for it. Maybe you will find some hints in the comments of the request.
The following shows how to use Joda Time to extract any date information from a Java Date type with Joda Times format() function and use it to build a new Date() using Joda Time's parse() function.
static DateTimeFormat dtf = DateTimeFormat.getFormat("yyyy-MM-dd HH:mm:ss.SSS");
static DateTimeFormat datefmt = DateTimeFormat.getFormat("yyyy-MM-dd ");
static DateTimeFormat timefmt = DateTimeFormat.getFormat("HH:mm:ss.SSS");
public Date getDateTime(Date date, Date time) {
String datetime = datefmt.format(date) + timefmt.format(time);
return dtf.parse(datetime);
}
Have you tried adding actual code of the class to your project? Some Java SDK classes compile well even though they are not in JRE white list.
For those who prefer implementing the math directly, here is a solution for how to add days to an existing date object without using Calendar or any deprecated functions:
private Date addDays(Date dateIn, int numDays)
{
long milisPerDay = 86400000;
// convert the dateIn to milliseconds
long dateInMilis = dateIn.getTime();
// add numDays to the date
dateInMilis = dateInMilis + (numDays * milisPerDay);
return new Date(dateInMilis);
}
Here's how to get the current year as a String (very useful for Copyright notices)
long time = System.currentTimeMillis();
long milisPerYear = new BigInteger("31536000000").longValue();
String currentYear = String.valueOf((int) Math.floor(time / milisPerYear) + 1970);
Finding the constants such as number of miliseconds in a day, year, etc. is easy with Google. The tricky part is adding months, since the number of milliseconds in a month is going to depend on the month. If there's any demand for it, I'd be happy to write a function and post it here in order to add and subtract months.

Java Date vs Calendar

Could someone please advise the current "best practice" around Date and Calendar types.
When writing new code, is it best to always favour Calendar over Date, or are there circumstances where Date is the more appropriate datatype?
Date is a simpler class and is mainly there for backward compatibility reasons. If you need to set particular dates or do date arithmetic, use a Calendar. Calendars also handle localization. The previous date manipulation functions of Date have since been deprecated.
Personally I tend to use either time in milliseconds as a long (or Long, as appropriate) or Calendar when there is a choice.
Both Date and Calendar are mutable, which tends to present issues when using either in an API.
The best way for new code (if your policy allows third-party code) is to use the Joda Time library.
Both, Date and Calendar, have so many design problems that neither are good solutions for new code.
Date and Calendar are really the same fundamental concept (both represent an instant in time and are wrappers around an underlying long value).
One could argue that Calendar is actually even more broken than Date is, as it seems to offer concrete facts about things like day of the week and time of day, whereas if you change its timeZone property, the concrete turns into blancmange! Neither objects are really useful as a store of year-month-day or time-of-day for this reason.
Use Calendar only as a calculator which, when given Date and TimeZone objects, will do calculations for you. Avoid its use for property typing in an application.
Use SimpleDateFormat together with TimeZone and Date to generate display Strings.
If you're feeling adventurous use Joda-Time, although it is unnecessarily complicated IMHO and is soon to be superceded by the JSR-310 date API in any event.
I have answered before that it is not difficult to roll your own YearMonthDay class, which uses Calendar under the hood for date calculations. I was downvoted for the suggestion but I still believe it is a valid one because Joda-Time (and JSR-310) are really so over-complicated for most use-cases.
tl;dr
advise the current "best practice" around Date and Calendar
is it best to always favour Calendar over Date
Avoid these legacy classes entirely. Use java.time classes instead.
For a moment in UTC, use Instant(the modern equivalent of Date)
For a moment in a particular time zone, use ZonedDateTime(the modern equivalent of GregorianCalendar)
For a moment in a particular offset-from-UTC, use OffsetDateTime(no equivalent in legacy classes)
For a date-time (not a moment) with unknown time zone or offset, use LocalDateTime(no equivalent in legacy classes)
Details
The Answer by Ortomala Lokni is right to suggest using the modern java.time classes rather than the troublesome old legacy date-time classes (Date, Calendar, etc.). But that Answer suggests the wrong class as equivalent (see my comment on that Answer).
Using java.time
The java.time classes are a vast improvement over the legacy date-time classes, night-and-day difference. The old classes are poorly-designed, confusing, and troublesome. You should avoid the old classes whenever possible. But when you need to convert to/from the old/new, you can do so by calling new methods add to the old classes.
For much more information on conversion, see my Answer and nifty diagram to another Question, Convert java.util.Date to what “java.time” type?.
Searching Stack Overflow gives many hundreds of example Questions and Answers on using java.time. But here is a quick synopsis.
Instant
Get the current moment with an Instant. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
Instant instant = Instant.now();
ZonedDateTime
To see that same simultaneous moment through the lens of some particular region’s wall-clock time, apply a time zone (ZoneId) to get a ZonedDateTime.
Time zone
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone();
Offset
A time zone is a region’s history of changes in its offset-from-UTC. But sometimes you are given only an offset without the full zone. In that case, use the OffsetDateTime class.
ZoneOffset offset = ZoneOffset.parse( "+05:30" );
OffsetDateTime odt = instant.atOffset( offset );
Use of a time zone is preferable over use of a mere offset.
LocalDateTime
The “Local” in the Local… classes means any locality, not a particular locality. So the name can be counter-intuitive.
LocalDateTime, LocalDate, and LocalTime purposely lack any information about offset or time zone. So they do not represent actual moments, they are not points on the timeline. When in doubt or in confusion, use ZonedDateTime rather than LocalDateTime. Search Stack Overflow for much more discussion.
Strings
Do not conflate date-time objects with strings that represent their value. You can parse a string to get a date-time object, and you can generate a string from a date-time object. But the string is never the date-time itself.
Learn about standard ISO 8601 formats, used by default in the java.time classes.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Using a JDBC driver compliant with JDBC 4.2 or later, you may exchange java.time objects directly with your database. No need for strings nor java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
Date is best for storing a date object. It is the persisted one, the Serialized one ...
Calendar is best for manipulating Dates.
Note: we also sometimes favor java.lang.Long over Date, because Date is mutable and therefore not thread-safe. On a Date object, use setTime() and getTime() to switch between the two. For example, a constant Date in the application (examples: the zero 1970/01/01, or an applicative END_OF_TIME that you set to 2099/12/31 ; those are very useful to replace null values as start time and end time, especially when you persist them in the database, as SQL is so peculiar with nulls).
I generally use Date if possible. Although it is mutable, the mutators are actually deprecated. In the end it basically wraps a long that would represent the date/time. Conversely, I would use Calendars if I have to manipulate the values.
You can think of it this way: you only use StringBuffer only when you need to have Strings that you can easily manipulate and then convert them into Strings using toString() method. In the same way, I only use Calendar if I need to manipulate temporal data.
For best practice, I tend to use immutable objects as much as possible outside of the domain model. It significantly reduces the chances of any side effects and it is done for you by the compiler, rather than a JUnit test. You use this technique by creating private final fields in your class.
And coming back to the StringBuffer analogy. Here is some code that shows you how to convert between Calendar and Date
String s = "someString"; // immutable string
StringBuffer buf = new StringBuffer(s); // mutable "string" via StringBuffer
buf.append("x");
assertEquals("someStringx", buf.toString()); // convert to immutable String
// immutable date with hard coded format. If you are hard
// coding the format, best practice is to hard code the locale
// of the format string, otherwise people in some parts of Europe
// are going to be mad at you.
Date date = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH).parse("2001-01-02");
// Convert Date to a Calendar
Calendar cal = Calendar.getInstance();
cal.setTime(date);
// mutate the value
cal.add(Calendar.YEAR, 1);
// convert back to Date
Date newDate = cal.getTime();
//
assertEquals(new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH).parse("2002-01-02"), newDate);
Dates should be used as immutable points in time; Calendars are mutable, and can be passed around and modified if you need to collaborate with other classes to come up with a final date. Consider them analogous to String and StringBuilder and you'll understand how I consider they should be used.
(And yes, I know Date isn't actually technically immutable, but the intention is that it should not be mutable, and if nothing calls the deprecated methods then it is so.)
With Java 8, the new java.time package should be used.
Objects are immutable, time zones and day light saving are taken into account.
You can create a ZonedDateTime object from an old java.util.Date object like this:
Date date = new Date();
ZonedDateTime zonedDateTime = date.toInstant().atZone(ZoneId.systemDefault());
I always advocate Joda-time. Here's why.
the API is consistent and intuitive. Unlike the java.util.Date/Calendar APIs
it doesn't suffer from threading issues, unlike java.text.SimpleDateFormat etc. (I've seen numerous client issues relating to not realising that the standard date/time formatting is not thread-safe)
it's the basis of the new Java date/time APIs (JSR310, scheduled for Java 8. So you'll be using APIs that will become core Java APIs.
EDIT: The Java date/time classes introduced with Java 8 are now the preferred solution, if you can migrate to Java 8
A little bit late at party, but Java has a new Date Time API in JDK 8. You may want to upgrade your JDK version and embrace the standard. No more messy date/calendar, no more 3rd party jars.
Date should be re-developed. Instead of being a long interger, it should hold year, month, date, hour, minute, second, as separate fields. It might be even good to store the calendar and time zone this date is associated with.
In our natural conversation, if setup an appointment at Nov. 1, 2013 1pm NY Time, this is a DateTime. It is NOT a Calendar. So we should be able to converse like this in Java as well.
When Date is stored as a long integer (of mili seconds since Jan 1 1970 or something), calculating its current date depends on the calendar. Different calendars will give different date. This is from the prospective of giving an absolute time (eg 1 trillion seconds after Big Bang). But often we also need a convenient way of conversation, like an object encapsulating year, month etc.
I wonder if there are new advances in Java to reconcile these 2 objectives. Maybe my java knowledge is too old.
Btw "date" is usually tagged as "obsolete / deprecated" (I dont know exactly why) - something about it is wrote there
Java: Why is the Date constructor deprecated, and what do I use instead?
It looks like it's a problem of the constructor only- way via new Date(int year, int month, int day), recommended way is via Calendar and set params separately .. (Calendar cal = Calendar.getInstance();
)
I use Calendar when I need some specific operations over the dates like moving in time, but Date I find it helpful when you need to format the date to adapt your needs, recently I discovered that Locale has a lot of useful operations and methods.So I'm using Locale right now!

Categories

Resources