Oracle database: using Char(X) or Numeric(X) instead of Date - java

I have found some issues with the date type in Oracle databases. I have to manage an important amount of data, and they don't seem to work as well as expected with indexes and other stuff. The important thing is that I have decided to use another type for it.
My options are:
numeric(8) for "date" and numeric(6) for "time"
char(8) for "date" and char(6) for "time"
The fields are formatted as YYYYMMAA for date and HHMMSS for time.
The order of priorities (pondered) are:
Performance querying the fields separately (x3.5)
Performance querying the fields joined as one (date + time) (x3)
Usability from java (x2)
Legibility of the database (x1)
Which type would you suggest to use and why?
Thanks! :)

I would recommend to use still a date type. It will be stored as a number anyway ;) . But if you preffer to store it as a number or char, the 20151019 as a number makes more sense :) (also from size & performance perspective) btw, date format will be even smaller

ISO 8601
When you must serialize a date-time value as a string, use the standard ISO 8601 formats. Here are examples of a few of the formats:
Date-only example: 2015-10-18
Date-time example: 2015-10-18T14:26:16Z
Week-of-year: 2015-W42
This entire standard is surprisingly well thought-out and practical. The strings alphabetical order also happen to be chronological (when in UTC, and when consistent with resolving to whole or fraction of the second).
The hyphens are optional, considered by the spec to be the the "basic" version of the formats; I suggest including the hyphens unless storage/memory is critically scarce. The hyphens make the strings recognizable as date-time representations, and are easier to read by humans.
When creating reports, exporting data, writing XML or JSON, or otherwise exchanging data, I suggest almost always using these standard formats. Both (a) the new java.time framework built into Java 8 and later, (b) the Joda-Time library use these formats by default when parsing and generating string representations of date-time values.
Specifications Discordance
Note that while both ISO 8601 and the SQL standard are decades old, they seemed to have not crossed paths. The SQL standard has similar formats but not quite the same. Specifically ISO 8601 uses a T between the date and time-of-day portions whereas the SQL spec never does so.
Also some proprietary types use their own string formats, such as Oracle 11g using DD-MON-YY as the default for DATE type, for example '13-NOV-92'.
java.time
The java.time framework built into Java 8 and later has extended the ISO 8601 format for date-time by appending the name of the time zone in brackets.
The standard uses only an offset-from-UTC. A true time zone is an offset plus a set of rules for making adjustments for anomalies such as Daylight Savings Time (DST).
Use The Data-Type, Luke
Like the others commenting, I strongly recommend you learn and use your database’s native data types for date-time work. Some like SQLite have weak support for date-time, but most have decent to excellent support (such as H2 and Postgres).
These data types vary widely. The SQL spec defines some, but some databases such as Oracle additionally have proprietary types. Often those proprietary types are old outmoded types.
Even the standard data types are not so standard. You should play around and experiment outside your project so as to cement your understanding of their behavior.
The "issues" you experienced are most likely a misunderstanding of the specific type or of date-time handling in general. If so, rolling you own data type (via strings) will only exacerbate your problems in the long run. Invest some time in searching StackOverflow to learn about date-time handling. The subject of date-time is surprisingly tricky.
Numbers
As for using numbers as a roll-your-own date-time type, nearly all the native date-time data types use numbers internally. So no performance advantage in doing your own.

Related

Java best way/recommended data structure to represent date in a month, e.g, 01 January

There is often a task to represent a month, e.g,
January
, or a date in a month, e.g.,
01 January
, in a generic way, without specifying the year.
A caveat: quite often the captured data (e.g, user choice or input of other type) needs storing in a DB - SLQ or NoSQ. And that is subsequently used for reporting, for example, using date range aggregation.
Is there any consensus/recommendations on which Java data type is best to use for the above scenario?
I see the following 3 options:
Use Java Date, within the "0th" year, e.g, 01 January 1970, and then
use Date operations to extract only the required fields (DAY,
MONTH), and strip out all the rest. Libraries such as Joda or Java8
come handy here. Saving to DB is straightforward here, although the
programmatic overhead could be quite high.
Use contrived data type, e.g., ENUM, to list all months, or use numeric value for a month and provide mapping, then parse and shoe-horn further to capture the day in a month. Mapping to a DB field is not too difficult.
Use String, e.g, "01 January". Seems straightforward enough.
nos.2 and 3 could be less programming-intensive, but an added disadvantage that such a dates may be clunky when used in reporting, as aggregation by time period is not straightforward.
Any suggestions/thoughts on the above?
Edit:
It looks like the option #1 is the best (most flexible, least resistance, easiest for persistence, and best for subsequent reporting). New Java libraries make data manipulation and field extraction a relative doddle.
The java.time.MonthDay provides a ready made class, so you don't need to create your own. It'll also be usable with other java.time functionality, so that's probably your best bet. It should be fairly easy to persist as well.
MonthDay birthday = MonthDay.of(Month.JANUARY, 11);
The other two Answers describing the the java.time classes Month and MonthDay are correct and are well-advised. Similar is YearMonth.
Study the class documentation to find some handy methods. For example, Month::getDisplayName localizes the name of the month. Another example, you can get a date, a LocalDate from MonthDay by passing a year to the method atYear.
Avoid the troublesome old date-time classes found outside the java.time package. These old classes are now legacy, supplanted entirely by the java.time classes.
ISO 8601
For textual representation of such date-time values, look to the many formats defined by the ISO 8601 standard.
For month-day, the format is --MM-DD. For example, January 23 is:
--01-23
These ISO 8601 are especially useful for data exchange between systems.
The java.time classes use these standard formats by default when parsing/generating strings.
MonthDay md = MonthDay.parse( "--01-23" ) ;
String output = md.toString() ; // --01-23
For presentation to users, your audience may be amenable to reading the ISO 8601 formats. If not, you can generate strings from your java.time objects. Use DateTimeFormatter.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "MMM dd" , Locale.CANADA_FRENCH ) ;
String output = md.format( f );
janv. 23
Or for Locale.US:
Jan. 23
Use objects, not strings & integers
Use objects from the java.time classes whenever possible rather than crude strings and mere integers.
For months, do not use 1-12 numbers. Instead of 3 for the month of March, use Month.MARCH. Instead of 04 July for the month-day of July 4th, use the MonthDay object generated by MonthDay.of( Month.JULY , 4 ).
Pass around such objects as method arguments rather than passing strings or numbers. Use these java.time types to define member fields when composing a class.
Using such objects gives you these benefits:
Type-safety( avoid accidentally using the string of "tuesday" as a month )
Ensures valid values( no mistaken month of 13 )
Makes your code more self-documenting and easier to read.
JDBC
For exchanging data with a database, JDBC drivers compliant with JDBC 4.2 can work directly with the java.time types. Call:
PreparedStatement::setObject
ResultSet::getObject
No need to use the java.sql types not strings for fetching and storing date-time values.
As for your specific problem of string and retrieving month-day values, we have a problem as standard SQL does not define such a type. I would use a text or varchar type to store a seven-character string in the ISO 8601 format discussed above: --MM-DD. Call the MonthDay methods parse and toString.
These standard formats are wisely designed to be chronological when sorted alphabetically. So sorting a ResultSet in the database will work well as will queries for a range of month-day values.
The 3 options you are considering are already there in a Month enum since Java 8
Month month = Month.valueOf("July".toUpperCase());
System.out.println(month);
System.out.println(Month.AUGUST);

Java Calendar/Date Minvalue Supported on DB/Rest

I'm using Spring Boot, and HSQLDB file,
When i use:
calendar.setTimeInMillis(-9223372036854775808L);
calendar.setTime(new Date(Long.MIN_VALUE));
and and store the model,
after i call rest client, i get invalid date, when i check it, it returns some positive value instead of negative one :| what should i use as min_Value.
i thought it may be SQL issue, i changed temporary variable type from timespan to Date, but didn't worked again, i no longer sure what is the case of this issue, and what nuber i should use, every one talk about min value, some one talked about around -8.......L too that work in JS, but it didn't worked here too :|
Avoid ancient date-time values
Many reasons to not use that minimum number as a date value. As commented, standard SQL does not permit such ancient dates. No database implementation I know of supports that value. And using a date-time for historical values is fraught with problems and issues, and ill-advised.
Use epoch as a flag value
If you are looking for an arbitrary value to use as a flag such as "no value intended" while avoiding the use of nulls, then I suggest using the Java and Unix epoch of first moment of 1970 in UTC. If you know your system will never store any date-time that far back as a valid value, this will work well. And 1970-01-01T00:00:00Z is easily recognized by many programmers, DBAs, and SysAdmins as the common epoch and therefore likely to be a special value.
java.time
Avoid using the Date and Calendar classes. These troublesome classes and their siblings are now legacy, supplanted by the java.time classes.
These classes include a constant for that epoch value: Instant.EPOCH
Similar Question: Minimum date in Java

Timestamps and time zone conversions in Java and MySQL

I'm developing a Java application with a MySQL database on a server located in a different time zone from mine, and I am trying to decide between using DATETIME or TIMESTAMP on my database.
After reading questions like Should I use field 'datetime' or 'timestamp'?, and the MySQL documentation, I decided TIMESTAMP was better for me as it converts values to UTC for storage, and back to the current time zone for retrieval.
Also, as user Jesper explains in this thread, java.util.Date objects are internally only a UTC timestamp (i.e. number of milliseconds since the Epoch), and when you do a toString() it is displayed according to your current time zone.
For me, that looks like a good practice: storing datetimes as UTC timestamps, and then displaying them according to the current time zone.
I was about to do it like that, but then I found this from the Java documentation for Prepared Statements and got very confused:
void setTimestamp(int parameterIndex,
Timestamp x,
Calendar cal)
throws SQLException
Sets the designated parameter to the given java.sql.Timestamp value,
using the given Calendar object. The driver uses the Calendar object
to construct an SQL TIMESTAMP value, which the driver then sends to
the database. With a Calendar object, the driver can calculate the
timestamp taking into account a custom timezone. If no Calendar object
is specified, the driver uses the default timezone, which is that of
the virtual machine running the application.
Before this, I thought timestamps were by convention always in UTC. Why on earth would anyone want a localized timestamp instead of a localized representation of it? Wouldn't that be very confusing for everyone?
How do these conversions work? If Java takes an UTC timestamp and converts it to an arbitrary time zone, how can it tell MySQL in which timezone it is?
Won't MySQL assume that this timestamp is in UTC and then retrieve an incorrect localized value?
Date-Time Handling Is A Mess
The first paragraph in the answer by Teo is quite insightful and correct: Date-time handling in Java is a mess. Ditto for all other languages & development environments that I know of. Date-time work is difficult and tricky, especially error-prone and frustrating because we think it of date-time intuitively. But "intuitively" does not cut it when it comes to data types, databases, serialization, localization, adjusting across time zones, and all the other formalities that come with computer programming.
Unfortunately, the computer industry basically chose to ignore this problem of date-time work. Just as Unicode took too long to be invented given the obvious need, so too has the industry kicked the can down the road on solving the problem of date-time handling.
Do Not Rely On Count-Since-Epoch
But I must disagree with its conclusion. Working with a count-since-epoch is not the best solution. Using count-since-epoch is inherently confusing and error-prone and incompatible.
Humans cannot read a long number and decipher that as a date-time. So verifying data and debugging becomes complicated, to say the least.
What "count" would you use? The milliseconds used by java.util.Date and by Joda-Time? The microseconds used by Postgres, MySQL, and other databases? The nanoseconds used by the new java.time package in Java 8?
Which epoch would you use? The Unix epoch of the beginning of 1970 in UTC is common, but far from singular. Almost two dozen epochs have been used by various computer systems.
We create numeric data types for doing math rather than using bits. We create string classes to handle the nitty-gritty details of handling text rather than bare octets. So too we should create data-types and classes to handle date-time values.
The early Java teams (and IBM & Taligent before them) made an attempt with the java.util.Date and java.util.Calendar and related classes. Unfortunately, the attempt was inadequate. While date-time is inherently confusing, these classes have added even more confusion.
Joda-Time
As far as I know, the Joda-Time project was the first project to take on date-time in a thorough, competent, and successful manner. Even so, the creators of Joda-Time were not entirely satisfied. They went on to create the java.time package in Java 8, and extend that work with the threeten-extra project. Joda-Time and java.time share similar concepts but are distinct, each having some advantages.
Database Problems
Specifically, the java.util.Date & .Calendar classes lack date-only values without time-of-day and time zone. And they lack time-only values without date and time zone. Before Java 8, the Java team added the hacks known as the java.sql.Date and java.sql.Time classes which is a date-time value masquerading as a date-only. Both Joda-Time and java.time rectify that by offering LocalDate and LocalTime classes.
Another specific problem is that java.util.Date has a resolution of milliseconds, but databases frequently use microseconds or nanoseconds. In an ill-advised attempt to bridge this disparity, the early Java team created another hack, the java.sql.Timestamp class. While technically a java.util.Date subclass, it also tracks the fractional seconds to nanosecond resolution. So when converting in and out of this type you may losing or gaining the finer fractional seconds granularity without being conscious of that fact. So that might mean that values you expect to be equal are not.
Another source of confusion is the SQL data type, TIMESTAMP WITH TIME ZONE. That name is a misnomer as the time zone info is not stored. Think of the name as TIMESTAMP WITH RESPECT FOR TIME ZONE as any passed time zone offset info is used in converting the date-time value to UTC.
The java.time package with its nanosecond resolution has some specific features to better communicate date-time data with a database.
I could write much more, but such information can be gleaned from searching StackOverflow for words such as joda, java.time, sql timestamp, and JDBC.
Example using Joda-Time with JDBC with Postgres. Joda-Time uses immutable objects for thread-safety. So rather than alter an instance ("mutate"), we create a fresh instance based on the values of the original.
String sql = "SELECT now();";
…
java.sql.Timestamp now = myResultSet.getTimestamp( 1 );
DateTime dateTimeUtc = new DateTime( now , DateTimeZone.UTC );
DateTime dateTimeMontréal = dateTimeUtc.withZone( DateTimeZone.forID( "America/Montreal" ) );
Focus On UTC
Before this, I thought timestamps were by convention always in UTC. Why on earth would anyone want a localized timestamp instead of a localized representation of it? Wouldn't that be very confusing for everyone?
Indeed. The SQL standard defines a TIMESTAMP WITHOUT TIME ZONE which ignores and strips away any included time zone data. I cannot imagine the usefulness of that. This Postgres expert, David E. Wheeler, says as much in recommending always using TIMESTAMP WITH TIME ZONE. Wheeler cites one narrow technical exception (partitioning) and even then says to convert all the values to UTC yourself before saving to the database.
The best practice is to work and store data in UTC while adjusting to localized time zones for presentation to the user. There may be times when you want to remember the original date-time data in its localized time zone; if so, save that value in addition to converting to UTC.
Guidelines
The first steps to better date-time handling are avoiding java.util.Date & .Calendar, using Joda-Time and/or java.time, focusing on UTC, and learning the behavior of your specific JDBC driver and your specific database (databases vary widely in their date-time handling despite the SQL standard).
MySQL
Caveat: I don’t use MySQL (I'm a Postgres kind of guy).
According to the version 8 documentation, the two types DATETIME and TIMESTAMP differ in that the first one lacks any concept of time zone or offset-from-UTC. The second one uses any indication of time zone or offset-from-UTC accompanying an input to adjust that value to UTC, then stores it, and discards the zone/offset info.
So these two types seem to be akin to the standard SQL types:
MySQL DATETIME ≈ SQL-standard TIMESTAMP WITHOUT TIME ZONE
MySQL TIMESTAMP ≈ SQL-standard TIMESTAMP WITH TIME ZONE
For MySQL DATETIME, use the Java class LocalDateTime. That class, like that data type, purposely lacks any concept of time zone or offset-from-UTC. Use this type and class for either:
When you mean any zone or all zones, such as “Christmas starts on first moment of December 25, 2018”. That translates to different moments in different places as a new day dawns earlier in the east than in the west.
When scheduling appointments or events far enough out in the future that politicians may change the offset of the time zone, for which politicians around the world have shown a proclivity. In this usage, you must at runtime apply a time zone to dynamically calculate, but not store, a moment for display on a calendar. That way, a 15:00 dental appointment in 8 months remains at 15:00 even if politicians redefine the clock to be minutes/hours ahead or behind.
For MySQL TIMESTAMP, use the Java class Instant, as shown above. Use this type and class for moments, specific point on the timeline.
JDBC 4.2
As of JDBC 4.2 and later, we can directly exchange java.time objects with the database. Use getObject & setObject methods.
myPreparedStatement.setObject( … , Instant.now() ) ;
Retrieval.
Instant instant = myResultSet.getObject( … , Instant.class ) ;
The JDBC 4.2 specification requires a driver to support OffsetDateTime but strangely does not require support for the more common types Instant and ZonedDateTime. But converting between types is quite easy.
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
Instant instant = odt.toInstant() ;
You can then adjust that UTC value in Instant to a specific time zone for presentation to a user.
ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
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.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, 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 (<26), 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.
Your question is spot on a problem which i think is huge these days. Both DB (via SQL) and server side itself (via programming languages such as Java) offer a compendium of ways of dealing with date and time. I would qualify the status-quo as highly non-standardized and a bit chaotic (personal opinion :)
My answer is partial but i'll explain why.
You're correct, Java's Date (and Calendar) store time as milliseconds since the Unix Epoch (which is great). It happens not only in Java but in other programming languages as well. In my opinion the perfect time-keeping architecture emerges naturally from this: the Unix Epoch is January 1st, 1970, midnight, UTC. Therefore if you choose to store time as milliseconds since the Unix Epoch you have a lot of benefits:
architecture clarity: server side works with UTC, client side shows the time through its local timezone
database simplicity: you store a number (milliseconds) rather than complex data structures like DateTimes
programming efficiency: in most programming languages you have date/time objects capable of taking milliseconds since Epoch when constructed (which as you said, allows for automatic conversion to client-side timezone)
I find code and architecture is much simpler and more flexible when using this approach. I stopped trying to understand things like DateTime (or Timestamp) and only deal with them when i have to fix legacy code.

Differences between Java 8 Date Time API (java.time) and Joda-Time

I know there are questions relating to java.util.Date and Joda-Time. But after some digging, I couldn't find a thread about the differences between the java.time API (new in Java 8, defined by JSR 310) and Joda-Time.
I have heard that Java 8’s java.time API is much cleaner and can do much more than Joda-Time. But I cannot find examples comparing the two.
What can java.time do that Joda-Time cannot?
What can java.time do better than Joda-Time?
Is the performance better with java.time?
Common features
a) Both libraries use immutable types. Joda-Time also offers additional mutable types like MutableDateTime.
b) Furthermore: Both libraries are inspired by the design study "TimeAndMoney" from Eric Evans or ideas from Martin Fowler about domain driven style so they strive more or less for a fluent programming style (although not always perfect ;-)).
c) With both libraries we get a real calendar date type (called LocalDate), a real wall time type (called LocalTime) and the composition (called LocalDateTime). That is a very big win compared with old java.util.Calendar and java.util.Date.
d) Both libraries use a method-centric approach meaning they encourage the user to use getDayOfYear() instead of get(DAY_OF_YEAR). This causes a lot of extra methods compared with java.util.Calendar (although latter is not type-safe at all due to excessive use of ints).
Performance
See the other answer by #OO7 pointing to the analysis of Mikhail Vorontsov although point 3 (exception catching) is probably obsolete - see this JDK-bug. The different performance (which is in general favour of JSR-310) is mainly due to the fact that the internal implementation of Joda-Time always use a machine-time-like long-primitive (in milliseconds).
Null
Joda-Time often use NULL as default for system timezone, default locale, current timestamp etc. while JSR-310 almost always rejects NULL values.
Precision
JSR-310 handles nanosecond precision while Joda-Time is limited to millisecond precision.
Supported fields:
An overview about supported fields in Java-8 (JSR-310) is given by some classes in the temporal-package (for example ChronoField and WeekFields) while Joda-Time is rather weak on this area - see DateTimeFieldType. The biggest lack of Joda-Time is here the absence of localized week-related fields. A common feature of both field implementation design is that both are based on values of type long (no other types, not even enums).
Enum
JSR-310 offers enums like DayOfWeek or Month while Joda-Time does not offer this because it was mainly developed in years 2002-2004 before Java 5.
Zone API
a) JSR-310 offers more timezone features than Joda-Time. Latter is not able to yield a programmatical access to the history of timezone offset transitions while JSR-310 is capable to do this.
b) For your information: JSR-310 has moved its internal timezone repository to a new location and a different format. The old library folder lib/zi does not exist any more.
Adjuster vs. Property
JSR-310 has introduced the TemporalAdjuster-interface as a formalized way to externalize temporal calculations and manipulations, especially for library or framework-writers this is a nice and relative easy way to embed new extensions of JSR-310 (a kind of equivalent to static helper classes for former java.util.Date).
For most users however, this feature has very limited value because the burden to write code is still with the user. Built-in solutions based on the new TemporalAdjuster-concept are not so many, there is currently only the helper class TemporalAdjusters with a limited set of manipulations (and the enums Month or other temporal types).
Joda-Time offers a field-package but practice has shown evidence that new field implementations are very hard to code. On the other side Joda-Time offers so-called properties which make some manipulations much easier and more elegant than in JSR-310, for example property.withMaximumValue().
Calendar systems
JSR-310 offers 4 extra calendar systems. The most interesting one is Umalqura (used in Saudi Arabia). The other 3 are: Minguo (Taiwan), Japanese (only the modern calendar since 1871!) and ThaiBuddhist (only correct after 1940).
Joda-Time offers an Islamic calendar based on calculatory base - not a sighting-based calendar like Umalqura. Thai-Buddhist is also offered by Joda-Time in a similar form, Minguo and the japanese one not. Otherwise Joda-Time offers coptic and ethiopic calendar, too (but without any support for internationalization).
More interesting for Europeans: Joda-Time also offers a Gregorian, Julian and mixed-gregorian-julian calendar. However, the practical value for real historical calculations is limited because important features like different year starts in date history are not supported at all (the same criticism is valid for old java.util.GregorianCalendar).
Other calendars like Hebrew or Persian or Hindu are completely missing in both libraries.
Epoch days
JSR-310 has the class JulianFields while Joda-Time (version 2.0) offers some helper methods in the class DateTimeUtils.
Clocks
JSR-310 has no interface (a design mistake) but an abstract class java.time.Clock which can be used for any clock dependency injection. Joda-Time offers the interface MillisProvider and some helper methods in DateTimeUtils instead. So this way Joda-Time is also capable of supporting test-driven models with different clocks (mocking etc.).
Duration arithmetic
Both libraries support the calculation of time distances in one or more temporal units. However, when handling single-unit-durations the JSR-310-style is obviously nicer (and long-based instead of using int):
JSR-310 => long days = ChronoUnit.DAYS.between(date1, date2);
Joda-Time => int days = DAYS.daysBetween(date1, date2).getDays();
Handling of multiple-unit-durations are also different. Even the calculation results can differ - see this closed Joda-Time issue. While JSR-310 use a very simple and limited approach to use just the classes Period (duration based on years, months and days) and Duration (based on seconds and nanoseconds), Joda-Time uses a more sophisticated way using the class PeriodType in order to control in which units a duration (Joda-Time call it "Period") shall be expressed. While the PeriodType-API is somehow awkward to use a similar way is not offered by JSR-310 at all. Especially it is not yet possible in JSR-310 to define mixed date and time durations (based on days and hours for example). So be warned if it comes to migration from one library to another. The libraries in discussion are incompatible - despite of partially same class names.
Intervals
JSR-310 does not support this feature while Joda-Time has limited support. See also this SO-answer.
Formatting and Parsing
Best way to compare both libraries is to view the equal-named classes DateTimeFormatterBuilder (JSR-310) and DateTimeFormatterBuilder (Joda-Time). The JSR-310-variant is a little bit more powerful (can also handle any kind of TemporalField provided the field implementor has managed to code some extension points like resolve()). Most important difference is however - in my opinion:
JSR-310 can much better parse timezone names (format pattern symbol z) while Joda-Time could not do this at all in its earlier versions and now only in a very limited way.
Another advantage of JSR-310 is support for standalone month names which is important in languages like Russian or Polish etc. Joda-Time has no access to such resources - not even on Java-8 platforms.
The pattern syntax in JSR-310 is also more flexible than in Joda-Time, allows for optional sections (using square brackets), is more orientated towards CLDR-standard and offers padding (letter symbol p) and more fields.
Otherwise it should be noted that Joda-Time can format durations using PeriodFormatter. JSR-310 cannot do this.
Hope this overview helps. All the gathered information is mainly there due to my efforts and investigations how to design and implement a better date-and-time library (nothing is perfect).
Update from 2015-06-24:
Meanwhile I have found the time to write and publish a tabular overview for different time libraries in Java. The tables also contain a comparison between Joda-Time v2.8.1 and Java-8 (JSR-310). It is more detailed than this post.
Java 8 Date/Time :
Java 8 classes are built around the human time. It makes them fast for human datetime arithmetics/conversion.
Date/time component getters like getDayOfMonth have O(1) complexity in Java 8 implementation.
Parsing of OffsetDateTime/OffsetTime/ZonedDateTime is very slow in Java 8 ea b121 due to exceptions thrown and caught internally in the JDK.
A set of packages: java.time.*, java.time.chrono.*, java.time.format.*, java.time.temporal.*, java.time.zone.*
Instants (timestamps) Date and Time Partial Date and Time Parser and Formatter Time zones Different chronologies (calendars).
Existing classes have issues like Date has no support for I18N or L10N. They are mutable!
Simpler & more robust.
Clocks can be injected.
Clocks can be created with various properties - Static clocks, Mocked clocks, Low-precision clocks (whole seconds, whole minutes, etc).
Clocks can be created with specific time zones. Clock.system(Zone.of("America/Los_Angeles")).
Makes code handling date and time testable.
Makes tests independent of timezone.
Joda-Time :
Joda-Time is using machine time inside. A manual implementation based on int/long values would be much faster.
Joda-Time getters require the computer-to-human time calculation on every getter call, which makes Joda-Time a bottleneck in such scenarios.
It is composed of immutable classes it handles Instants, Date & Time, Partials, and Durations It is flexible It is well designed.
Represents dates as instants. But a date&time may correspond to more than one instant. Overlap hour when daylight savings end. As well as not have any instant that corresponds to it at all. Gap hour when daylight starts. Has to perform complex computations for simple operations.
Accepts nulls as valid values on most of its methods. Leads to subtle bugs.
For more detailed comparision see :-
Java 8 Date/Time library performance (as well as Joda-Time 2.3 and j.u.Calendar). &
New Date & Time API in Java 8
Joda-Time is now in maintenance-mode
Not a direct answer to the question but the Joda-Time project is no longer in active development. The team suggests users migrate to the newer java.time API. See tutorial by Oracle.
From the official GitHub project page:
Joda-time is no longer in active development except to keep timezone
data up to date. From Java SE 8 onwards, users are asked to migrate to
java.time (JSR-310) - a core part of the JDK which replaces this
project. For Android users, java.time is added in API 26+. Projects
needing to support lower API levels can use the ThreeTenABP library.
The project has been led jointly by the author of Joda-Time (Stephen Colebourne) and Oracle, under JSR 310, and will appear in the new Java SE 8 package java.time.
https://www.oracle.com/technical-resources/articles/java/jf14-date-time.html

Timezone issue in webapp

I want to know a best practice of dealing with timezone in web app.
Let take an example, Server is in UTC timezone, user1 and user2 both are in different time zone. what is a proper way to deal with date?
When user1 add a new date it is in different timezone and Server is in UTC so should I convert date to UTC and store in database?
When displaying date fetch date which is in UTC format and then convert it according to client timezone and show it. Is it proper way?
What is DST issue? is it effect this process?
Somewhere I read that store date in mili seconds only is it good idea? right now I store as a date/time.
is there any proper method or library to do this please suggest
My issue is
client with GMT +5:30 create a record and set delivery date and time let say june 30 2014 11:30 PM GMT +5:30
So Transporter with GMT -3:00 can see a exact local time in GMT -3:00 which client select. How to achieve this ?
1
Yes. Usually best practice is to store all your date-time values in UTC. Your business logic should work in UTC.
You may want to also store the value input by user or outside data source as an audit trail or debugging aid. But use UTC for the official record.
Yes the server's time zone should be set to UTC (or, if not possible, use Reykjavík Iceland). But do not depend on this in your programming. Specify your desired time zone in your code rather than rely on defaults.
2
Yes. Convert to a localized time for presentation. Unless, of course, the user prefers UTC.
Think of it as part of localization. When you internationalize, you work with key values in your code. Then upon presentation, you use the key value to look up a localized translation string to display to the user.
3
Non-issue. If by "DST" you mean Daylight Saving Time, the use of a decent date-time library will automatically handle adjustments for DST. Caveat: you need to keep the time zone definition list used by your library up-to-date as governments frequently change the rules.
If adjusting for DST (or time zones) causes confusion or misinformation with your users, then you should be displaying UTC in that case.
4
No. Do not store or work with milliseconds in most cases. Databases and date-time libraries may do so internally, but you should not.
Some nerdy types will suggest tracking milliseconds. But working with date-time as milliseconds is like working with text as byte arrays. We use libraries of code with higher levels of abstraction to handle all the complexities of text (UTF-8, Unicode normalization of diacriticals, etc.) and add helpful methods (search, replace, etc.). So it is with date-time.
Furthermore, using milliseconds will cause confusion and make debugging difficult as you cannot readily make sense of their value. Date-time work is inherently tricky and error-prone. Using milliseconds does not help.
And not all databases and other libraries use milliseconds internally. Some use whole seconds, or microseconds, or nanoseconds. Nor do they all use the same epoch.
5
In Java we have two good date-time libraries: Joda-Time and java.time (Java 8).
The java.time package was inspired by Joda-Time but is re-architected. They share similar concepts, but are not identical. You can use both in your code as long as you are careful with your import statements. Both have their own strengths and weaknesses.
Avoid j.u.Date/.Calendar
Do not use the java.util.Date and .Calendar classes bundled with Java. They are notoriously troublesome, flawed both in design and in implementation. They have been supplanted by Sun/Oracle with the new java.time package.
Both Joda-Time and java.time include handy methods to translate to/from a java.util.Date object for when some other class requires a j.u.Date object.
Bonus Tips
Regarding text formats:
Avoid that string format you used in your question. It is unwieldy and difficult to parse.
Learn about using various string formats defined by the ISO 8601 standard for textual representations of date-time values.
Do not drop that leading zero in the offsets, as you did in your question. That will break code in libraries, and violates standards requirements. Always write +05:30, never +5:30. Make that a habit even when writing prose, not just in your programming code.
Example Code
Example code with Joda-Time 2.3.
Instantiate the date-time, local to a +05:30 offset. I arbitrarily chose Kolkata time zone. You would replace with appropriate one of course.
DateTimeZone timeZoneKolkata = DateTimeZone.forID( "Asia/Kolkata" );
DateTime dateTimeKolkata = new DateTime( 2014, DateTimeConstants.JUNE, 30, 23, 30, 0, timeZoneKolkata );
Adjust the same moment to another time zone with a -03:00 offset. I arbitrarily chose America/Buenos_Aires.
DateTimeZone timeZoneBuenos_Aires = DateTimeZone.forID( "America/Buenos_Aires" );
DateTime dateTimeBuenos_Aires = dateTimeKolkata.withZone( timeZoneBuenos_Aires );
Convert to UTC.
DateTime dateTimeUtc = dateTimeKolkata.withZone( DateTimeZone.UTC );

Categories

Resources