Saturday, September 12, 2015

Java 8 Date and Time



Java timezone, zoneId handles day time saving correctly
ZoneId timeZone = ZoneId.of("America/New_York");
DateTimeFormatter dataTimePattern = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
assertThat(LocalDateTime.parse("2017-01-01 11:11:11", dataTimePattern).atZone(timeZone)
        .format(DateTimeFormatter.ISO_DATE_TIME), is("2017-01-01T11:11:11-05:00[America/New_York]"));
assertThat(LocalDateTime.parse("2017-07-01 11:11:11", dataTimePattern).atZone(timeZone)
        .format(DateTimeFormatter.ISO_DATE_TIME), is("2017-07-01T11:11:11-04:00[America/New_York]"));
https://www.mkyong.com/java8/java-8-zoneddatetime-examples/
        String date = "2016-08-22 14:30";
        LocalDateTime ldt = LocalDateTime.parse(date, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
        System.out.println("LocalDateTime : " + format.format(ldt));

        //Paris, 2016 Apr-Oct = DST, UTC+2, other months UTC+1
        //UTC+2
        ZonedDateTime parisDateTime = ldt.atZone(ZoneId.of("Europe/Paris"));
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
        LocalDateTime formatDateTime = LocalDateTime.parse(now, formatter);
http://stackoverflow.com/questions/19431234/converting-between-java-time-localdatetime-and-java-util-date
Despite its name, java.util.Date represents an instant on the time-line, not a "date". The actual data stored within the object is a long count of milliseconds since 1970-01-01T00:00Z (midnight at the start of 1970 GMT/UTC).
The equivalent class to java.util.Date in JSR-310 is Instant, thus there are convenient methods to provide the conversion to and fro:
Date input = new Date();
Instant instant = input.toInstant();
Date output = Date.from(instant);
java.util.Date instance has no concept of time-zone. This might seem strange if you call toString() on a java.util.Date, because the toString is relative to a time-zone. However that method actually uses Java's default time-zone on the fly to provide the string. The time-zone is not part of the actual state of java.util.Date.
An Instant also does not contain any information about the time-zone. Thus, to convert from an Instant to a local date-time it is necessary to specify a time-zone. This might be the default zone - ZoneId.systemDefault() - or it might be a time-zone that your application controls, such as a time-zone from user preferences. LocalDateTime has a convenient factory method that takes both the instant and time-zone:
Date in = new Date();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());
In reverse, the LocalDateTime the time-zone is specified by calling the atZone(ZoneId) method. The ZonedDateTime can then be converted directly to an Instant:
LocalDateTime ldt = ...
ZonedDateTime zdt = ldt.atZone(ZoneId.systemDefault());
Date output = Date.from(zdt.toInstant());
http://javarevisited.blogspot.com/2017/04/5-reasons-why-javas-old-date-and-Calendar-API-bad.html
1) It's not intuitive
Look at the following example, here a user simply wants to create a Date object for 25th December 2017, 8.30 at night, do you think this is the right way to represent that date in Java?

Date date = new Date(2017, 12, 25, 20, 30);

Well, even though it is looking alright, it is not correct. The above code contains two bugs, which is not at all intuitive. If you are using the java.util.Date class then you must know that year starts from 1900 and month starts from zero i.e. January is the zeroth month, not the first.

Here is the right way to declare same date in Java:

int year = 2017 - 1900;
int month = 12 - 1;
Date date = new Date(year, month, 25, 20, 30);

You must remember that January is 0, December is 11 and Date use years from 1900.
2) Timezones
Prior to JDK 8, Java uses String to represent TimeZone, a very bad idea. Ideally, they should have defined a constant or Enum instead of allowing the user to pass String. Since String lacks compiler checks, it opens a door for spelling mistakes and silly human errors. Java's naming convention with timezones also doesn't help. Look at the following example, here I am trying to get TimeZone object for NewYork, doesn't it look all right?

TimeZone zone = TimeZone.getInstance("America/NewYork");

Unfortunately, it's not correct. It contains a silly but hard to find a mistake, the time zone string is wrong here. Correct timezone String is "America/New_York" as shown in the following example

TimeZone zone = TimeZone.getInstance("America/New_York");

Had they have used Enum, these would have been flagged by the compiler or your IDE as soon as you typed. Another example of this kind of gotcah is "Asia/Hong_Kong", so be careful while using those timezones in Java.
The Calendar class is also not very user-friendly or intuitive in Java. You just cannot apply common sense or predictive knowledge. For example in the following code, we are trying to create a Calendar object for a date in a particular timezone, It will not show any compile time error but it will not work as you expect.

Calendar cal = new GregorianCalendar(date, zone);

Right way of using Calandar object with date and timezone is as following :

Calendar cal = new GregorianCalendar(zone);
cal.setTime(date);

ormatting date was very tricky in Java. One of the most useful utility to format dates, SimpleDateFormat was not thread-safe.

DateFormat fm = new SimpleDateFormat("HH:mm Z");
String str = fm.format(cal);

This example contains a couple of bugs, first, you have to set Timezone for DateFormat class and second, you cannot pass a Calendar object to format method, you can only pass a java.util.Date object, hence you need to first convert Calendar to Date in Java and then pass it to the format() method as shown below:

Here is the right way of using Calendar class with SimpleDateFormat in Java.

DateFormat fm = new SimpleDateFormat("HH:mm Z");
fm.setTimeZone(zone);
Date calDate = cal.getTime();
String str = fm.format(calDate);


You must remember that Calendar cannot be formatted in Java and DateFormat class is not thread-safe so it cannot be used in multi-threaded Java application without proper synchronization. This issue has been addressed in Java 8 by making DateFormatter immutable and thread-safe

5) Mutable
This is IMHO biggest mistake Java designers has made in the JDK. Unlike String or Integer, Date is mutable. It's possible for you to pass a client to get reference of Date and change it without owner of that Date class knowing, as shown in below example

Persons p = new Person();

Date birthDay = p.getBirthDay();
birthDay.setTime();

Now that person will have a different birth date, so bad. That's why whenever you have to return Date from your class, you must return a new Date object or clone, you should never return the original Date object, it breaks the Encapsulation of class.


If these reasons were not enough, the SQL Date/Time/Timestamp also extends the java.util.Date class and violates the Liskov Substitution Principle, which means if a method expects the java.util.Date object then you cannot pass the java.sql.Datejava.sql.Time, or java.sql.Timestamp class, even though they are a subclass of java.util.Date, hence you need to convert util date to SQL date and vice-versa while passing around your application's DAO layer and Business layer.

Not to forget the memory consumption of Calender. It's more then 400 bytes just for representing one instance of a date. 

http://stackoverflow.com/questions/6403851/parsing-time-strings-like-1h-30min
Duration parsing is now included in Java 8. Use standard ISO 8601 format with Duration.parse.
Duration d = Duration.parse("PT1H30M")
You can convert this duration to the total length in milliseconds. Beware that Duration has a resolution of nanoseconds, so you may have data loss going from nanoseconds to milliseconds.
long milliseconds = d.toMillis();
https://www.mkyong.com/java8/java-8-period-and-duration-examples/
 you can use ChronoUnit.{unit}.between to find out the difference between dates
java.time.Period example to find out differently (years, months, days) between two LocalDates
http://stackoverflow.com/questions/27005861/calculate-days-between-two-dates-in-java-8
Use DAYS.between() method from java.time.temporal.ChronoUnit instead:
LocalDate dateBefore;
LocalDate dateAfter;
long daysBetween = DAYS.between(dateBefore, dateAfter);
In case a duration is what you are interested in, you can use that class instead:
LocalDate today = LocalDate.now()
LocalDate yeasterday = today.minusDays(1);
Duration oneDay = Duration.between(today, yesterday);
Duration.between(today.atTime(0, 0), yesterday.atTime(0, 0)).toDays() // another option
http://tutorials.jenkov.com/java-date-time/localdate.html
The LocalDate class in the Java 8 date time API represents a local date which is a date without time zone information. A local date could be a birthdate or official holiday etc. which relates to a specific day of the year - not the precise time of that day (the moment the day starts).
LocalDate localDate = LocalDate.now();
Another way to create a LocalDate is to create it from year, month and day information, like this:
LocalDate localDate2 = LocalDate.of(2015, 12, 31);

  • plusDays()
  • plusWeeks()
  • plusMonths()
  • plusYears()
  • minusDays()
  • minusWeeks()
  • minusMonths()
  • minusYears()
http://tutorials.jenkov.com/java-date-time/localtime.html
The LocalTime class in the Java 8 date time API represents a specific time of day without any time zone information. For instance, 10.00 AM . The LocalTime instance can be used to describe e.g. when school or work starts in different countries, where you are not interested in the UTC time, but the time in the respective countries. Of course you could also represent that as UTC time with a time zone, but you can also just use a LocalTime object without time zone information.
LocalTime localTime2 = LocalTime.of(21, 30, 59, 11001);

LocalTime localTimeLater   = localTime.plusHours(3);
LocalTime localTimeEarlier = localTime.minusHours(3);

http://stackoverflow.com/questions/36188428/java-8-date-equivalent-to-jodas-datetimeformatterbuilder-with-multiple-parser-f
There is no direct facility to do this, but you can use optional sections. Optional sections are enclosed inside squared brackets []. This allows for the whole section of the String to parse to be missing.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(""
    + "[yyyy/MM/dd HH:mm:ss.SSSSSS]"
    + "[yyyy-MM-dd HH:mm:ss[.SSS]]"
    + "[ddMMMyyyy:HH:mm:ss.SSS[ Z]]"
);
This formatter defines 3 grand optional sections for the three main patterns you have. Each of them is inside its own optional section.
Working demo code:
public static void main(String[] args) {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(""
        + "[yyyy/MM/dd HH:mm:ss.SSSSSS]"
        + "[yyyy-MM-dd HH:mm:ss[.SSS]]"
        + "[ddMMMyyyy:HH:mm:ss.SSS[ Z]]"
    , Locale.ENGLISH);
    System.out.println(LocalDateTime.parse("2016/03/23 22:00:00.256145", formatter));
    System.out.println(LocalDateTime.parse("2016-03-23 22:00:00", formatter));
    System.out.println(LocalDateTime.parse("2016-03-23 22:00:00.123", formatter));
    System.out.println(LocalDateTime.parse("23Mar2016:22:00:00.123", formatter));
    System.out.println(LocalDateTime.parse("23Mar2016:22:00:00.123 -0800", formatter));
}
https://eyalsch.wordpress.com/2009/05/29/sdf/
Every instance of SimpleDateFormat has an associated time zone to work with, as a TimeZone instance. Otherwise, a parsing operation would not be able to determine an absolute point in time (Date object), from a given string denoting a date. If not specified otherwise, the time zone associated with a new SimpleDateFormat is the default one, corresponding to the time zone reported by the operating system.
Consider the following code:
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
Date date = sdf.parse("18-07-1976");
System.out.println(date.getTime());
Since the time zone is not explicitly set (using setTimeZone(..)), the code above will result in different outputs when executed in different parts of the world. The midnight that started July 18, 1976 at Thailand, and the same midnight in Florida, have a different GMT representation. The reason is that the midnight arrived in Thailand first.
However, on a client-server application, or on a distributed system, we usually want to avoid this time zone relativity. Date strings that are read from configuration / data files / user interface / external software interfaces must be specific with their time zone. We can achieve this in one of two ways. The first one is to include the timezone itself as a part of the expected date format:
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy z");
Date date = sdf.parse("18-07-1976 ICT");
System.out.println(date.getTime());
This program will always return the same value (206470800000), regardless of the execution location.
The other approach is to define a convention which needs to be respected by all system entities which generate textual dates. For example, we can decide that all dates should be interpreted as GMT dates. Then, we can bind the corresponding time zone to the SimpleDateFormat.
impleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
Date d = null;
try {
    d = sdf.parse(dateStr);
} catch (ParseException e) {   
    showErrorMessage("Incorrect date format. "+e.getMessage());
}
Will it do the job? The answer is – not always. Date strings such as “10//10/2008” will result in an error, but dates such as “40/20/2009” will be parsed successfully, with no error message!. The reason is that by default, SimpleDateFormat is lenient, which means that it is tolerant to some formatting errors. It will try to figure out the date by applying some heuristics to the given text. In the case above, month 20 will be interpreted as December plus 8 months (i.e. August 2010), and day 40 of the month will be interpretted as end of August plus 9 days. The resulting date will be September 9th, 2010.
In order to achieve a stricter validation, we should make the SimpleDateFormat non-lenient, by initializing it as follows:
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
sdf.setLenient(false);

SimpleDateFormat is not thread safe. Concurrent formatting/parsing operations interfere with each other and result in inconsistent behavior. 

1) Create a SimpleDateFormat instance per usage
This will work fine if the usage is not frequent. Otherwise, the performance penalty may be significant.
3) Use an instance per thread
The usage of ThreadLocal class allows associating a single instance of SimpleDateFormat with each thread that needs to do parsing/formatting of dates.
This way, we achieve both thread safety with no thread contention, and a minimal number of SimpleDateFormat instances.
In some cases, we can be extra economical on memory usage, if we know for example that the threads stop using the SimpleDateFormat at some point of time. In these cases, we could use a soft reference to hold the SimpleDateFormat instance.

http://www.javaspecialists.eu/archive/Issue172.html
    DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
    Date d = df.parse("2009-01-28-09:11:12");
    System.err.println(d);
  
Since the date format was different to the incoming text, she was getting the rather strange result of "Sun Nov 30 22:07:51 CET 2008".
The SimpleDateFormat is by default lenient and tries to fit our dates into the format as best it can.
Instead, we should rather create a ThreadLocal that gives each thread his own copy of the DateFormat class. With ThreadLocal, we want to set the value the first time the thread requests it and then simply use that in future.
  private static final ThreadLocal<DateFormat> tl =
      new ThreadLocal<DateFormat>() {
        protected DateFormat initialValue() {
          return new SimpleDateFormat("yyyy/MM/dd");
        }
      };
As long as the thread is alive, this thread local would stay set, even if he never used the DateFormat again. We could instead use a SoftReference as a value for the ThreadLocal:
  private static final ThreadLocal<SoftReference<DateFormat>> tl
      = new ThreadLocal<SoftReference<DateFormat>>();

  private static DateFormat getDateFormat() {
    SoftReference<DateFormat> ref = tl.get();
    if (ref != null) {
      DateFormat result = ref.get();
      if (result != null) {
        return result;
      }
    }
    DateFormat result = new SimpleDateFormat("yyyy/MM/dd");
    ref = new SoftReference<DateFormat>(result);
    tl.set(ref);
    return result;
  }
http://stackoverflow.com/questions/26142864/how-to-get-utc0-date-in-java8
ZonedDateTime utc = ZonedDateTime.now(ZoneOffset.UTC);
Date to ZonedDateTime
ZonedDateTime.ofInstant(date.toInstant(), ZoneOffset.UTC);
According to this SO question, and ZonedDateTime's ofInstant(), one way is like so:
ZonedDateTime z = ZonedDateTime.ofInstant(dateObject.toInstant(), ZoneId);

To transform an Instant to a ZonedDateTimeZonedDateTime offers the method ZonedDateTime.ofInstant(Instant, ZoneId). So
So, assuming you want a ZonedDateTime in the default timezone, your code should be
ZonedDateTime d = ZonedDateTime.ofInstant(calculateFromDate.toInstant(),
                                          ZoneId.systemDefault());
http://stackoverflow.com/questions/21939967/java-simpledateformat-interpret-parse-string-as-utc
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
Date d = sdf.parse("22/09/1985");

ZonedDateTime d = ZonedDateTime.ofInstant(calculateFromDate.toInstant(),
                                          ZoneId.systemDefault());
ZonedDateTime z = ZonedDateTime.ofInstant(dateObject.toInstant(), ZoneId);

ZonedDateTime utc = ZonedDateTime.now(ZoneOffset.UTC);
To answer your comment, you can then convert it to a Date (unless you depend on legacy code I don't see any reason why) or to millis since the epochs:
Date date = Date.from(utc.toInstant());
ZoneOffset extends ZoneId
https://davidkeen.com/blog/2015/11/java-8-date-time-api-cheatsheet/
https://blog.tompawlak.org/java-8-conversion-new-date-time-api
  1. java.util.Date will be converted to the Instant instace (Date.toInstant()) and then
  2. LocalDateTime will be created from the Instant object using LocalDateTime.ofInstant().
Note that you will need to provide a time zone during the last step of conversion. I've used system default zone in this example:
Date dateToConvert = new Date();
LocalDateTime dateTime = LocalDateTime.ofInstant(dateToConvert.toInstant(), ZoneId.systemDefault());

Date dateToConvert = new Date();
LocalDate dateOnly = LocalDateTime.ofInstant(
    dateToConvert.toInstant(), ZoneId.systemDefault()).toLocalDate();



LocalDateTime dateTimeToConvert = LocalDateTime.now();
Date convertToDate = Date.from(dateTimeToConvert.atZone(ZoneId.systemDefault()).toInstant());
LocalDate dateToConvert = LocalDate.now();
Date convertToDate =
    Date.from(dateToConvert.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
http://stackoverflow.com/questions/4534924/how-to-iterate-through-range-of-dates-in-java
// 4 days between (end is inclusive in this example)
Stream.iterate(start, date -> date.plusDays(1))
        .limit(ChronoUnit.DAYS.between(start, end) + 1)
        .forEach(System.out::println);

List<LocalDate> daysRange = Stream.iterate(startDate, date -> date.plusDays(1)).limit(numOfDays).collect(toList());

http://codingjunkie.net/java-8-dates-part1/
assertThat(today.until(vacationStart, ChronoUnit.DAYS), is(127L));
http://www.nurkiewicz.com/2016/08/guide-to-time-and-date-in-java.html
A great alternative to Date is java.time.Instant. It does precisely what it claims: stores an instant in time. Instantdoes not have date or calendar related methods, its toString() uses familiar ISO format in UTC time zone (more on that later) and most importantly: it's immutable. If you want to remember when a particular event happened, Instant is the best you can get in plain Java:

1
2
Instant now = Instant.now();
Instant later = now.plusSeconds(60);
Notice that Instant does not have plusMinutes()plusHours() and so on. Minutes, hours and days are concepts related to calendar systems, whereas Instant is geographically and culturally agnostic.

You can create ZonedDateTime from Instant only by providing a time zone. Otherwise default system time zone is used which you have no control over. Converting Instant to ZonedDateTime in any way without providing explicit ZoneId is probably a bug:

Instant now = Instant.now();
System.out.println(now);
ZonedDateTime dateTime = ZonedDateTime.ofInstant(
        now,
        ZoneId.of("Europe/Warsaw")
    );
System.out.println(dateTime);

By default you should store and send time either as timestamp (long value) or as ISO 8601 which is basically what Instant.toString() does as per the documentation. Prefer long value as it is more compact, unless you need more readable format in some text encoding like JSON. Also long is timezone-agnostic so you are not pretending that the timezone you send/store has any meaning. This applies both to transmitting time and storing it in database.

By default you should store and send time either as timestamp (long value) or as ISO 8601 which is basically what Instant.toString() does as per the documentation. Prefer long value as it is more compact, unless you need more readable format in some text encoding like JSON. Also long is timezone-agnostic so you are not pretending that the timezone you send/store has any meaning. This applies both to transmitting time and storing it in database.
http://blog.eyallupu.com/2013/07/java-8-apis-javautiltime-instant.html
Probably the best place to start with the java.time package is the Instant class. An Instant represents a point in time (similar to java.util.Date) with nanoseconds precision (unlike the old Date which has milliseconds precision). Representing a point in time using nanoseconds precision requires more space than a Long can provide, therefore the internal representation is composed of two Long fields, the first holds the number of seconds since (or before) the standard Java epoch and the other the number of nanoseconds of the last seconds (so never larger than 999,999,999).

// Convert a java.util.Date into an Instant
Instant instant = Instant.ofEpochMilli(new Date().getTime());

// Create from a String
instant = Instant.parse("1995-10-23T10:12:35Z");

The second example above creates an Instant by parsing a String, this string must by a valid representation of a UTC Instant (NB: Instant is a point of time, it doesn't store any TimeZone information and as such it supports only UTC formatted strings). Instant API provides some useful methods to allow calculations using Instants and other classes in the package, below is a first example:

// Adding 5 hours and 4 minutes to an Instant
instant.plus(Duration.ofHours(5).plusMinutes(4));

How many instances of java.time.Instant are used in the example above? Two. The java.time package is planned to be thread safe and as such most of its classes are immutable, Instant is not an exception to that rule and as such the plus() method creates a new instance.

Instant instant1 = instant.plus(Duration.ofHours(5).plusMinutes(4));

// How many minutes are between to Instants?
long diffAsMinutes = instant.periodUntil(instant1, ChronoUnit.MINUTES); // Option 1
long diffAsMinutes = ChronoUnit.MINUTES.between(instant, instant1); // Option 2

Instants are Comparable which means they can be used in any place a Comparable is expected (such as collections). Instant also provides the isAfter() and isBefore() methods which can make a more readable code.

http://stackoverflow.com/questions/20689055/java-8-instant-now-with-nanosecond-resolution
http://stackoverflow.com/questions/32437550/java-8-whats-the-difference-between-instant-and-localdatetime
LocalDateTime has no time zone. Having no time zone is the entire point of that class.
To quote that class’ doc:
This class does not store or represent a time-zone. Instead, it is a description of the date, as used for birthdays, combined with the local time as seen on a wall clock. It cannot represent an instant on the time-line without additional information such as an offset or time-zone.
So Local… means “not zoned”.

Instant

An Instant is a moment on the timeline in UTC, a count of nanoseconds since the epoch of the first moment of 1970 UTC (basically, see class doc for nitty-gritty details). Since most of your business logic, data storage, and data exchange should be in UTC, this is a handy class to be used often.

ZoneId

ZoneId is a time zone.

ZonedDateTime

The ZonedDateTime class is an Instant with an assigned ZoneId.
ZonedDateTime = Instant + ZoneId
Nearly all of your backend, database, business logic, data persistence, data exchange should all be in UTC. But for presentation to users you need to adjust into a time zone expected by the user. This is the purpose of the ZonedDateTime class and the formatter classes used to generate String representations of those date-time values.
http://blog.joda.org/2014/11/converting-from-joda-time-to-javatime.html
The java.time library contains many of the lessons learned from Joda-Time, including stricter null handling and a better approach to multiple calendar systems.

http://blog.joda.org/2009/11/why-jsr-310-isn-joda-time_4941.html
Classes not including a time-zone:
Joda-Timejava.timeNotes
LocalDateLocalDateSame concept - date without time or time-zone
YearMonthDay
LocalTimeLocalTimeSame concept - time without date or time-zone
TimeOfDay
LocalDateTimeLocalDateTimeSame concept - date and time without time-zone
MonthDayMonthDaySame concept - month and day without time-zone
YearMonthYearMonthSame concept - year and month without time-zone
-YearNew concept - a value type for the year
-MonthNew concept - an enum for the month-of-year
-DayOfWeekNew concept - an enum for the day-of-week
Partial-Not included in java.time
Classes including a time-zone or representing an instant:
Joda-Timejava.timeNotes
DateTimeZonedDateTimeSame concept - Date and time with time-zone
OffsetDateTimeNew concept - Date and time with offset from Greewich/UTC
MutableDateTime-Not included in java.time, use immutable ZonedDateTime instead
DateMidnight-Deprecated as a bad idea in Joda-Time, Use LocalDate or ZonedDateTime
-OffsetTimeNew concept - Time with offset from Greewich/UTC
InstantInstantSame concept - Instantaneous point on timeline
DateTimeZoneZoneIdSame concept - Identifier for a time-zone, such as Europe/Paris
ZoneOffsetNew concept - An offeset from Greenwich/UTC, such as +02:00
Amounts of time:
Joda-Timejava.timeNotes
DurationDurationSame concept - Amount of time, based on fractional seconds
PeriodPeriod and/or DurationSimilar concept - Amount of time
Joda-Time Period includes years to milliseconds, java.time only year/month/day
MutablePeriod-Not included in java.time, use immutable Period or Duration instead
Years-Not included in java.time, use Period instead (or ThreeTen-Extra)
Months
Weeks
Days
Hours-Not included in java.time, use Duration instead
Minutes
Seconds
Interval-Not included in java.time
MutableInterval-Not included in java.time
Formatting:
Joda-Timejava.timeNotes
DateTimeFormatterDateTimeFormatterSame concept - an immutable formatter
DateTimeFormatterBuilderDateTimeFormatterBuilderSame concept - a builder of the formatter
DateTimeFormatDateTimeFormatterConcepts exposed as static methods on DateTimeFormatter
ISODateTimeFormat
PeriodFormatter-Not included in java.time
PeriodFormatterBuilder
PeriodFormat
ISOPeriodFormat
Other classes and interfaces:
Joda-Timejava.timeNotes
-ClockNew concept - Standard way to pass around the current time
ChronologyChronologySimilar concept - Very different API and implementation
ISOChronologyIsoChronologySimilar concept - Very different API and implementation
DateTimeFieldTypeChronoFieldSimilar concept - Very different API and implementation
DateTimeField
DurationFieldTypeChronoUnitSimilar concept - Very different API and implementation
DurationField
PeriodType-Not included in java.time
Readable*Temporal*The Readable* interfaces are most closely replaced by the Temporal* interfaces
It is strongly recommended to use the value types, not the temporal interfaces

Odds and Ends

In most cases, the table above will be sufficient to identify the class to convert to. After that, in most cases the method needed will be obvious. Some special cases are noted below.
Rounding. Joda-Time has considerable support for rounding, java.time has less, based only on truncation. See the truncatedTo() methods.
End of month. Joda-Time has the withMaximumValue() method on the property object to change a field to the last day of the month. java.time has a more general mechanism, see TemporalAdjusters.lastDayOfMonth().
Nulls. Joda-Time accepts null as an input and handles it with a sensible default value. java.time rejects null on input.
Construction. Joda-Time has a constructor that accepts an Object and performs type conversion. java.time only has factory methods, so conversion is a user problem, although a parse() method is provided for strings.
Time between. Joda-Time provides methods on amount classes such as Days.between(a, b)java.time provides a similar method on the ChronoUnit classes - ChronoUnuit.DAYS.between(a, b).
Additional fields. Joda-Time provides a fixed set of fields in DateTimeFieldTypejava.time allows the set of fields to be extended by implementing TemporalUnit, see IsoFieldsJulianFields and WeekFields.

http://stackoverflow.com/questions/24631909/differences-between-java-8-date-time-api-java-time-and-joda-time

http://www.oracle.com/technetwork/articles/java/jf14-date-time-2125367.html
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.
The new API is driven by three core ideas: 
  • Immutable-value classes. One of the serious weaknesses of the existing formatters in Java is that they aren’t thread-safe. This puts the burden on developers to use them in a thread-safe manner and to think about concurrency problems in their day-to-day development of date-handling code. The new API avoids this issue by ensuring that all its core classes are immutable and represent well-defined values.
  • Domain-driven design. The new API models its domain very precisely with classes that represent different use cases for Date andTime closely. This differs from previous Java libraries that were quite poor in that regard. For example, 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.
    This emphasis on domain-driven design offers long-term benefits around clarity and understandability, but you might need to think through your application’s domain model of dates when porting from previous APIs to Java SE 8.
  • Separation of chronologies. The new API allows people to work with different calendaring systems in order to support the needs of users in some areas of the world, such as Japan or Thailand, that don’t necessarily follow ISO-8601. It does so without imposing additional burden on the majority of developers, who need to work only with the standard chronology. 
http://examples.javacodegeeks.com/core-java/java-8-datetime-api-tutorial/
The usage of the java.util.Date related classes had several problems:

















  • Concurrency problems: non Thread safe and statefull. This is a poor design.
  • Horrible naming: Date is not a date, but a timestamp, Calendar is mix of dates and times…
  • Difficulties to support different time zones.
  • SimpleDateFormat and Calendar have problems while working together.
  • Months start with 0, days with 1 and years with 1900!
  • Several things are just not possible: dates without years, 1 hour durations, periods of 3 months, dates without seconds…
  • The main design principles are that the used classes are inmmutable, that dates and times are separated and that it supports global calendars (although it is based on the ISO calendar). 

    Temporal Adjusters
    Adjusters are classes and interfaces with methods that “adjust” any kind of temporal value preserving its state, i.e. the state and values of the used temporal value does not change after applying the adjuster operations.

    Adjusters can be used in combination with a zone id (or with a ZonedDateTime) and its computations take into consideration the proper zone.

    LocalDate adjusted = now.with( TemporalAdjusters.lastDayOfMonth() );

    Time Zones
    ZonedDateTime contains information about a zone and about a concrete date and time.
    http://www.mscharhag.com/java/java-8-date-time-api
    By default LocalDate/Time classes will use the system clock in the default time zone. We can change this by providing a time zone or an alternative Clock implementation:
    // current (local) time in Los Angeles
    LocalTime currentTimeInLosAngeles = LocalTime.now(ZoneId.of("America/Los_Angeles"));

    // current time in UTC time zone
    LocalTime nowInUtc = LocalTime.now(Clock.systemUTC());

    The LocalDate/Timeclasses we have seen so far do not contain information about a time zone. If we want to work with a date/time in a certain time zone we can use ZonedDateTime or OffsetDateTime
    Timestamps
    Classes like LocalDate and ZonedDateTime provide a human view on time. However, often we need to work with time viewed from a machine perspective. For this we can use the Instant class which represents timestamps. An Instant counts the time beginning from the first second of January 1, 1970 (1970-01-01 00:00:00) also called the EPOCH. Instant values can be negative if they occured before the epoch.
    Instant fromUnixTimestamp = Instant.ofEpochSecond(1262347200);
    Instant fromEpochMilli = Instant.ofEpochMilli(1262347200000l);
    // parsing from ISO 8601

    Instant fromIso8601 = Instant.parse("2010-01-01T12:00:00Z");

    Periods and Durations
    Period and Duration are two other important classes. Like the names suggest they represent a quantity or amount of time. A Period uses date based values (years, months, days) while a Duration uses seconds or nanoseconds to define an amount of time. Duration is most suitable when working with Instants and machine time. 
    Period period = Period.between(firstDate, secondDate);
    Period twoMonthsAndFiveDays = Period.ofMonths(2).plusDays(5);

    Duration between = Duration.between(firstInstant, secondInstant);

    Formatting and parsing
    Formatting and parsing is another big topic when working with dates and times. In Java 8 this can be accomplished by using the format() and parse() methods:
    String asBasicIsoDate = dateTime.format(DateTimeFormatter.BASIC_ISO_DATE);

    // format as ISO week date (2014-W08-4)
    String asIsoWeekDate = dateTime.format(DateTimeFormatter.ISO_WEEK_DATE);

    // format ISO date time (2014-02-20T20:04:05.867)
    String asIsoDateTime = dateTime.format(DateTimeFormatter.ISO_DATE_TIME);

    // using a custom pattern (01/04/2014)
    String asCustomPattern = dateTime.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"));

    // french date formatting (1. avril 2014)
    String frenchDate = dateTime.format(DateTimeFormatter.ofPattern("d. MMMM yyyy", new Locale("fr")));


    InstantA point in time in nanoseconds from January 1st 1970
    DurationAn amount of time measured in nanoseconds
    Human time is based on fields that we use in our daily lifes such as day, hour, minute and second. It is represented by a group of classes, some of which we will discuss in this article.
    http://geekmonkey.org/2012/09/a-new-date-and-time-api-for-jdk-8/
    ClassDescription
    LocalDatea date, without time of day, offset or zone
    LocalTimethe time of day, without date, offset or zone
    LocalDateTimethe date and time, without offset or zone
    OffsetDatea date with an offset such as +02:00, without time of day or zone
    OffsetTimethe time of day with an offset such as +02:00, without date or zone
    OffsetDateTimethe date and time with an offset such as +02:00, without a zone
    ZonedDateTimethe date and time with a time zone and offset
    YearMontha year and month
    MonthDaymonth and day
    Year/MonthOfDay/DayOfWeek/...classes for the important fields
    DateTimeFieldsstores a map of field-value pairs which may be invalid
    Calendricalaccess to the low-level API
    Perioda descriptive amount of time, such as "2 months and 3 days"
    In addition to the above classes three support classes have been implemented. The Clock class wraps the current time and date, ZoneOffset is a time offset from UTC and ZoneId defines a time zone such as 'Australia/Brisbane'

    JDK 8 Code:

    LocalDate
        private final int year;
        private final short month;

        private final short day;

    LocalTime
        private final byte hour;
        private final byte minute;
        private final byte second;

        private final int nano;

    LocalDateTime
        private final LocalDate date;

        private final LocalTime time;

    Jackson
    https://blog.oio.de/2015/06/13/add-support-for-java-8-date-time-api-to-jackson-serialized-rest-web-services/
    https://github.com/FasterXML/jackson-datatype-jsr310

    Labels

    Review (572) System Design (334) System Design - Review (198) Java (189) Coding (75) Interview-System Design (65) Interview (63) Book Notes (59) Coding - Review (59) to-do (45) Linux (43) Knowledge (39) Interview-Java (35) Knowledge - Review (32) Database (31) Design Patterns (31) Big Data (29) Product Architecture (28) MultiThread (27) Soft Skills (27) Concurrency (26) Cracking Code Interview (26) Miscs (25) Distributed (24) OOD Design (24) Google (23) Career (22) Interview - Review (21) Java - Code (21) Operating System (21) Interview Q&A (20) System Design - Practice (20) Tips (19) Algorithm (17) Company - Facebook (17) Security (17) How to Ace Interview (16) Brain Teaser (14) Linux - Shell (14) Redis (14) Testing (14) Tools (14) Code Quality (13) Search (13) Spark (13) Spring (13) Company - LinkedIn (12) How to (12) Interview-Database (12) Interview-Operating System (12) Solr (12) Architecture Principles (11) Resource (10) Amazon (9) Cache (9) Git (9) Interview - MultiThread (9) Scalability (9) Trouble Shooting (9) Web Dev (9) Architecture Model (8) Better Programmer (8) Cassandra (8) Company - Uber (8) Java67 (8) Math (8) OO Design principles (8) SOLID (8) Design (7) Interview Corner (7) JVM (7) Java Basics (7) Kafka (7) Mac (7) Machine Learning (7) NoSQL (7) C++ (6) Chrome (6) File System (6) Highscalability (6) How to Better (6) Network (6) Restful (6) CareerCup (5) Code Review (5) Hash (5) How to Interview (5) JDK Source Code (5) JavaScript (5) Leetcode (5) Must Known (5) Python (5)

    Popular Posts