狠狠撸

狠狠撸Share a Scribd company logo
java.time.*
@kojilin?
2014/03/29@TWJUG
Java的Data和Time
?java.util.Date
?Since 1.0
?java.util.Calendar
?Since 1.1
?java.time.*
?Since 1.8
?為取代而生
Date
?雖然叫 Date, 但實際上是 timestamp,
#toString 又帶有 time zone
?存取麻煩
?年是1900 + ?
?月份從 0 開始
?不支援國際化
?Unix time
Calendar
?為了國際化而導入
?雖然叫 Calendar, 但實際上是 Date 和 Time
?建立和編輯日期與時間
?存取和運算比 java.util.Date 稍好一點,但仍
不敷使用
Calendar.Builder
Calendar cal1 = new Calendar.Builder()?
.setDate(2014, Calendar.MARCH, 29)?
.build();
?Java 8 新增,讓建立和變更能方便一點
Calendar cal2 = new Calendar.Builder()?
.setCalendarType("japanese") ?
.setFiled(YEAR, 1, DAY_OF_YEAR, 1)?
.build();
java.time.*
?JSR-310
?為了 JDK 設計
?從 Joda-Time 啓發和演化
?ISO 8601 為基礎
?Immutable
?Type-safe
?考慮到 XML 和 資料庫
ISO-8601
?國際標準化組織的國際標準ISO 8601是日期
和時間的表示方法
?hh:mm:ss.s
?YYYY-MM-DDThh:mm:ss
?nYnMnD
?Gregorian Calendar (1582)
ThreeTen backport project
?https://github.com/ThreeTen/
threetenbp
?JSR-310 backport to JDK 7
?最終會有一個釋出會和 JDK 8 正式版本相同
以人的角度看時間?
vs
以機器的角度看時間?
機器
?Instant
?從 Java Epoch 開始經過的時間
?1970-01-01T00:00:00Z
?支援到奈秒
?Duration
?兩個 Instant 之間的差距
?Clock
?模擬系統時鐘
Instant
Instant now = Instant.now();
//2014-03-29T14:23:25.223Z?
now.toString();
//2014-03-29T14:23:28.223Z ?
now.plusSeconds(3);
//2014-03-27T14:23:25.223Z?
now.minus(2, ChronoUnit.DAYS);
Duration
?顯示時間的量
?使用 seconds 和 nanoseconds 表示
?toString 結果會是 PTnHnMnS
?顯示時可以用 hours,minutes,seconds
和 nanoseconds
?用 of 建立?
Duration.ofHours(2);
Duration.ofDays(1);
?從兩個 Temporal 取得
!
?
?有 Day 相關的方法,但 邊的 Day 就是 24
Hours 的意思
// 兩個參數都必須支援 ChronoUnit.SECONDS?
Duration.between(LocalDateTime.now(), ?
LocalDateTime.now().plusDays(2));
!
!
!
// 現在時間加 24?
LocalDateTime.now().plus(?
Duration.ofDays(1));
人
?出生於 1983/12/11
?2月3日生
?營業時間是 14:00 到 22:00
?兩天,三小時
日期與時間
?LocalDate
?LocalTime
?LocalDateTime
?O?setTime
?O?setDateTime
?ZonedDateTime
Local 系列
?沒有帶時差和時區的資
?LocalDate
?12月5日生日
?LocalTime
?14:00 開始營業
?LocalDateTime
LocalDate
LocalDate now = LocalDate.now();
now.toString(); // 2014-03-29
now.getDayOfWeek(); // SATURDAY
now.getDayOfMonth(); // 29
now.isLeapYear(); // false
// 2014-04-10?
now.plusDays(12).toString();
LocalTime
LocalTime now = LocalTime.now();
now.toString(); // 14:20:42.270
now.getHour(); // 14
now.getMinute(); // 20
LocalTime.MIDNIGHT; // 00:00
LocalDateTime
LocalDateTime now = LocalDateTime.now();
// 2014-03-29T14:20:42.270?
now.toString();
now.getDayOfMonth(); // 29
now.getHour(); // 14
?LocalDate <=> LocalDateTime
Local 之間的轉換
LocalDate localDate = ?
LocalDate.now();
// LocalDate to LocalDateTime?
LocalDateTime localDateTime = ?
localDate.atTime(14, 20, 20);
// LocalDateTime to LocalDate?
localDate = ?
localDateTime.toLocalDate();
?LocalTime <=> LocalDateTime
LocalTime localTime = ?
LocalTime.now();
// LocalTime to LocalDateTime?
LocalDateTime localDateTime = ?
localTime.atDate(?
LocalDate.of(2014, 3, 29));
// LocalDateTime to LocalTime?
localTime = ?
localDateTime.toLocalTime();
時差和 time zone
?O?setTime
?O?setDateTime
?ZonedDateTime
?ZonedDateTime != O?setDateTime
?時差是固定的,Zoned 則會依照狀況變換
時差,例如:日光節約時間, 更改時差
ZonedDateTime dateTime = ?
ZonedDateTime.of( ?
LocalDate.of(1975, 3, 31),?
LocalTime.of(23, 0),?
ZoneId.of("Asia/Taipei"));
!
//1975-03-31T23:00+08:00[Asia/Taipei]?
dateTime.toString();
//1975-04-01T01:00+09:00[Asia/Taipei]?
dateTime.plusHours(1);
?台灣1975日光節約時間爲4月1日到9月30日
ZonedDateTime dateTime = ?
ZonedDateTime.of( ?
LocalDate.of(1979, 6, 30),?
LocalTime.of(23, 0),?
ZoneId.of("Asia/Taipei"));
!
//1979-06-30T23:00+09:00[Asia/Taipei]?
dateTime.toString();
?台灣1979日光節約時間爲7月1日到9月30日
Time zone
?ZoneO?set
?-18:00 +18:00(-12:00 +14:00)
?ZoneRules
?切換的規則
?ZoneId
?例如 Asia/Taipei, +8
Time zone data
?tz database 有世界時區的分類和命名
?IANA Time Zone Database (TZDB)
?$JDK_HOME/jre/lib/tzdb.dat
?透過 ZoneRulesProvider 讀取
?一直有更新,所以記得要持續更新 JRE 或透
過 Oracle 提供的工具更新
ZoneRuleProvider
?Service provider interface
?可以在 META-INF/services 自己提供
?系統預設是 TzdbZoneRuleProvider
?提供動態更新的方法
?帶來很多複雜的問題,例如:取消或減少暫存造
成效能問題,或是程式中拿不同規則來做運算
?通常不建議動態更新
public static boolean refresh() {
boolean changed = false;
for (ZoneRulesProvider provider : PROVIDERS) {
changed |= provider.provideRefresh();
}
return changed;
}
?ZoneRulesProvider.refresh
public static boolean refresh() {
boolean changed = false;
for (ZoneRulesProvider provider : PROVIDERS) {
changed |= provider.provideRefresh();
}
return changed;
}
?ZoneRulesProvider.refresh
?回傳的 boolean 可以讓應用程式知道有沒有更新
?系統預設的 provider#provideRefresh 是回傳 false
DateTime 之間的轉換
?LocalDateTime, LocalDate, LocalTime
?O?setDateTime, O?setTime
?ZonedDateTime
?補足需要的資 或拿掉多餘的資 就可以彼此
間轉換
DateTime 之間的轉換
?LocalDateTime, LocalDate, LocalTime
?O?setDateTime, O?setTime
?ZonedDateTime
?補足需要的資 或拿掉多餘的資 就可以彼此
間轉換
ZonedDateTime zdt = LocalDateTime.now()?
.atZone(ZoneId.of(“Asia/Taipei”));
LocalDateTime ldt = zdt.toLocalDateTime();
Period
?顯示時間的量
?使用 years, months 和 days 表示
?toString 結果會是 PnYnMnD
?用 of 建立?
Period.ofWeeks(2);
// 兩個參數都是 LocalDate?
Period.between(localDate1, LocalDate.now());
!
!
// 會是1975-04-01T23:00+09:00[Asia/Taipei]?
// 如果是 Duration, 則會是加上 24 小時?
ZonedDateTime.of( ?
LocalDate.of(1975, 3, 31),?
LocalTime.of(23, 0),?
ZoneId.of("Asia/Taipei"))?
.plus(Period.ofDays(1));
?從兩個 LocalDate 取得
!
!
?用在 ZonedDateTime 時有考慮到 DST
Formatting
?用 DateTimeFormatter 取代
SimpleDateFormat?
?
?
?
?Immutable - Thread safe
?可以利用 DateTimeFormatterBuilder 建立新
格式
DateTimeFormatter dateTimeFormatter = ?
DateTimeFormatter.ofPattern("yyyy/MM/dd");
localDate.format(dateTimeFormatter);
offset.format(dateTimeFormatter);
ISO_LOCAL_DATE = new DateTimeFormatterBuilder()
.appendValue(YEAR, 4, 10, ?
SignStyle.EXCEEDS_PAD)
.appendLiteral('-')
.appendValue(MONTH_OF_YEAR, 2)
.appendLiteral('-')
.appendValue(DAY_OF_MONTH, 2)
.toFormatter(ResolverStyle.STRICT, ?
IsoChronology.INSTANCE);
!
LocalDate ld = LocalDate.parse("2011-12-03",?
ISO_LOCAL_DATE);
Parsing
?Instant, Date 和 Time 類別都用一樣方式
parse?
?
?Period, Duration 用 ISO-8601格式
Instant.parse("…", dateTimeFormatter);
LocalDate.parse("…", dateTimeFormatter);
//1 Year 2 months 3days?
Period.parse("P1Y2M3D");
//2 days 3 hours 2.21 seconds?
Duration.parse("P2DT3H2.21S");
?有些格式變得比較嚴格
DateTimeFormatter formatter = ?
DateTimeFormatter.ofPattern(?
"yyyy/MM/dd");
//ok?
LocalDate.parse("2014/03/02", formatter);
// error, DateTimeParseException?
//LocalDate.parse("2014/3/2", formatter);
//ok?
new SimpleDateFormat("yyyy/MM/dd")?
.parse("2014/3/2");
Clock
?透過 Inject 便於測試?
?
?
?
?
?可以建立多種類型的 Clock
?讓測試可以獨立於 time zone
private Clock clock; // dependency inject
public void process(LocalDate event) {
if(event.isBefore(LocalDate.now(clock)){?
...
//使用系統?
Clock.systemDefaultZone();
//使用指定 ZoneId?
Clock.system(ZoneId.of("Asia/Tokyo"));
//固定時間?
Instant instant = … ;
Clock.fixed(instant, ?
ZoneIf.of("Asia/Taipei"));
//使用 30秒 tick 的時鐘?
Clock.tick(Clock.systemDefault(), ?
Duration.ofSeconds(30));
其他表示方式
?Year
?Month
?YearMonth
?MonthDay
?DayOfWeek
現在
LocalTime.now();
LocalTime.now(Clock.fixed(...));
LocalDate.now();
LocalDateTime.now();
OffsetDateTime.now();
of
?Static factory method
LocalDate.of(2014, 3, 29);
LocalTime.of(14, 5, 25);
Year.of(-1);
at
?Combines this object with another
LocalDate.of(2014, 3, 29).atTime(?
LocalTime.of(14, 5, 25));
parse
?Static factory method focussed on
parsing
LocalDate.parse("2014-03-29");
LocalTime.parse("14:23:20");
with
?The immutable equivalent of a setter
LocalDate.now().withMonth(4);
LocalTime.now().withMinute(30);
plus, minus
?Adds/Subtracts an amount to an object
LocalDate.now().plusDays(4)?
.plusYear(2);
LocalTime.now().plusMinutes(30)?
.plusHours(4)?
.minusSeconds(30);?
isBefore, isAfter
?Check order
LocalDate.now().isBefore(?
LocalDate.of(2014, 12, 3));
LocalTime.now().isAfter(?
LocalTime.of(4, 12, 31));
until, between
?Amount of time until another
LocalDate.of(2014, 12, 3).until(?
LocalDate.of(2014, 12, 7),?
ChronoUnit.WEEKS);
ChronoUnit.DAYS.between(?
LocalDate.of(2014, 12, 3), ?
LocalDate.of(2014, 12, 7));
Chronology
?Chronology
?曆
?Era
?紀年
?ChronoLocalDate
?ChronoLocalDateTime
?ChronoZonedDateTime
民國年
?MinguoDate
!
!
?和 ISO-8601 之間轉換
//Minguo ROC 103-03-29?
MinguoDate date = ?
MinguoDate.of(103, 3, 29);
LocalDate.from(?
MinguoDate.of(103, 3, 29));?
?
MinguoDate.from(?
LocalDate.now());
與 Date 的轉換
?LocalDate 和 LocalTime 本身沒有 Instant
值,所以必須要先轉換成能取得 Instant
?從 LocalDateTime 到 Date
LocalDate now = LocalDate.now();
Instant instant = ?
now.atZone(ZoneId.systemDefault())?
.toInstant();
Date date = Date.from(instant);
?從 Date 到 LocalDateTime
Date date = new Date();
Instant instant = date.toInstant();
LocalDateTime = ?
LocalDateTime.ofInstant(?
instant, ?
ZoneId.systemDefault());
可擴充的介面設計
?TemporalAccessor
?Temporal
?TemporalField
?TemporalAmount
?TemporalUnit
?TemporalQuery
?TemporalAdjuster
?可讀取的 Date&Time
?可修改的 Date&Time
?Date&Time 的 ?led
?時間的量
?Date&Time 的單位
?查詢 Date&Time
?修改 Date&Time
TemporalQuery
@FunctionalInterface
public interface TemporalQuery<R>{
R queryFrom(TemporalAccessor ?
temporal);
}
//Days?
LocalDate.of(2014, 3, 29)?
.query(TemporalQueries.precision());
//2014-03-29T16:30:26.043?
ZonedDateTime.now?
.query(LocalDateTime::from);
//SATURDAY?
LocalDate.of(2014, 3, 29)?
.query(DayOfWeek::from);
TemporalAdjuster
@FunctionalInterface
public interface TemporalAdjuster{
Temporal adjustInfo(Temporal ?
temporal);
}
//2014-03-31?
LocalDate.of(2014, 3, 29)?
.with(TemporalAdjusters.lastDayOfMondth());
//2014-04-05?
LocalDate.of(2014, 3, 29)?
.with(TemporalAdjusters.next(?
DayOfWeek.SATURDAY));
//2014-01-02?
LocalDate.now().with(t -> t.with(ChronoField?
.DAY_OF_YEAR, 2));
JDBC
?LocalDate
?LocalTime
?LocalDateTime?
?O?setTime
?O?setDateTime
?DATE
?TIME WITHOUT TIME ZONE
?TIMESTAMP WITHOUT TIME
ZONE
?TIME WITH TIME ZONE
?TIMESTAMP WITH TIMZ ZONE
LocalDateTime << SQL
ResultSet rs = …;
…
java.sql.Time time = rs.getTime(…);
LocalTime lt = time.toLocalTime();
java.sql.Date date = rs.getDate(…);
LocalDate ld = date.toLocalDate();
java.sql.Timestamp ts = rs.getTimeStamp(…);
LocalDateTime ldt = ?
ts.toLocalDateTime();
LocalDateTime >> SQL
PreparedStatement pstmt = …;
pstmt.setTime(1, ?
Time.valueOf(LocalTime.now()));
pstmt.setDate(2, ?
Date.valueOf(LocalDate.now()));
pstmt.setTimestamp(3, ?
Timestamp.valueOf(LocalDateTime.now()));
總結 JSR 310 的好處
?良好的命名和 API 設計
?日期和時間的分別處理
?Immutable
?精確到奈秒
?多樣化的操作
?存取各種 ?led 方便
Ad

Recommended

颁贬13:时间与日期
颁贬13:时间与日期
Justin Lin
?
第二堂 學習 Java 語法 (1) Java 歷史與程序開發
第二堂 學習 Java 語法 (1) Java 歷史與程序開發
力中 柯
?
使用 Java 上的 future/promise API
使用 Java 上的 future/promise API
koji lin
?
Java_06:Collection
Java_06:Collection
Brad Chao
?
Java_07:Thread
Java_07:Thread
Brad Chao
?
闯补惫补冲05:档案输出输入机制
闯补惫补冲05:档案输出输入机制
Brad Chao
?
Java Basic(1)
Java Basic(1)
Brad Chao
?
闯补惫补冲03:进阶物件导向观念
闯补惫补冲03:进阶物件导向观念
Brad Chao
?
第六堂 Youtube 播放 App (1)
第六堂 Youtube 播放 App (1)
力中 柯
?
第十一堂 學習編譯與上架
第十一堂 學習編譯與上架
力中 柯
?
Trading With Open Source Tools
Trading With Open Source Tools
clkao
?
Trading As Your Business
Trading As Your Business
derekhcw168
?
Java_08:SQL
Java_08:SQL
Brad Chao
?
闯补惫补冲02:初探物件导向程式设计
闯补惫补冲02:初探物件导向程式设计
Brad Chao
?
計量化交易策略的開發與運用 法人版
計量化交易策略的開發與運用 法人版
derekhcw168
?
藍色投機客 計量化交易策略的開發
藍色投機客 計量化交易策略的開發
guest87f844
?
开盘八法
开盘八法
Johnson ◎AUDI
?
Java 基本程式設計
Java 基本程式設計
Brad Chao
?
R統計軟體 -安裝與使用
R統計軟體 -安裝與使用
Person Lin
?
Machine Learning in R
Machine Learning in R
Alexandros Karatzoglou
?
沒有 GUI 的 Git
沒有 GUI 的 Git
Chia Wei Tsai
?
Hadoop, the Apple of Our Eyes (這些年,我們一起追的 Hadoop)
Hadoop, the Apple of Our Eyes (這些年,我們一起追的 Hadoop)
Kuo-Chun Su
?
Java SE 8 best practices
Java SE 8 best practices
Stephen Colebourne
?
程式交易經驗分享系列(4) 下單機設定及系列回顧
程式交易經驗分享系列(4) 下單機設定及系列回顧
Philip Zheng
?
程式交易經驗分享系列(3) 策略最佳化及wfa法
程式交易經驗分享系列(3) 策略最佳化及wfa法
Philip Zheng
?
程式交易經驗分享系列(2) 交易策略開發步驟
程式交易經驗分享系列(2) 交易策略開發步驟
Philip Zheng
?
程式交易經驗分享系列(1) 程式交易簡介及條件
程式交易經驗分享系列(1) 程式交易簡介及條件
Philip Zheng
?
Trading bot演算法與軟工在程式交易上的實踐
Trading bot演算法與軟工在程式交易上的實踐
Philip Zheng
?
サーバーサイドでの非同期処理で色々やったよ
サーバーサイドでの非同期処理で色々やったよ
koji lin
?
G1GC
G1GC
koji lin
?

More Related Content

Viewers also liked (20)

第六堂 Youtube 播放 App (1)
第六堂 Youtube 播放 App (1)
力中 柯
?
第十一堂 學習編譯與上架
第十一堂 學習編譯與上架
力中 柯
?
Trading With Open Source Tools
Trading With Open Source Tools
clkao
?
Trading As Your Business
Trading As Your Business
derekhcw168
?
Java_08:SQL
Java_08:SQL
Brad Chao
?
闯补惫补冲02:初探物件导向程式设计
闯补惫补冲02:初探物件导向程式设计
Brad Chao
?
計量化交易策略的開發與運用 法人版
計量化交易策略的開發與運用 法人版
derekhcw168
?
藍色投機客 計量化交易策略的開發
藍色投機客 計量化交易策略的開發
guest87f844
?
开盘八法
开盘八法
Johnson ◎AUDI
?
Java 基本程式設計
Java 基本程式設計
Brad Chao
?
R統計軟體 -安裝與使用
R統計軟體 -安裝與使用
Person Lin
?
Machine Learning in R
Machine Learning in R
Alexandros Karatzoglou
?
沒有 GUI 的 Git
沒有 GUI 的 Git
Chia Wei Tsai
?
Hadoop, the Apple of Our Eyes (這些年,我們一起追的 Hadoop)
Hadoop, the Apple of Our Eyes (這些年,我們一起追的 Hadoop)
Kuo-Chun Su
?
Java SE 8 best practices
Java SE 8 best practices
Stephen Colebourne
?
程式交易經驗分享系列(4) 下單機設定及系列回顧
程式交易經驗分享系列(4) 下單機設定及系列回顧
Philip Zheng
?
程式交易經驗分享系列(3) 策略最佳化及wfa法
程式交易經驗分享系列(3) 策略最佳化及wfa法
Philip Zheng
?
程式交易經驗分享系列(2) 交易策略開發步驟
程式交易經驗分享系列(2) 交易策略開發步驟
Philip Zheng
?
程式交易經驗分享系列(1) 程式交易簡介及條件
程式交易經驗分享系列(1) 程式交易簡介及條件
Philip Zheng
?
Trading bot演算法與軟工在程式交易上的實踐
Trading bot演算法與軟工在程式交易上的實踐
Philip Zheng
?
第六堂 Youtube 播放 App (1)
第六堂 Youtube 播放 App (1)
力中 柯
?
第十一堂 學習編譯與上架
第十一堂 學習編譯與上架
力中 柯
?
Trading With Open Source Tools
Trading With Open Source Tools
clkao
?
Trading As Your Business
Trading As Your Business
derekhcw168
?
闯补惫补冲02:初探物件导向程式设计
闯补惫补冲02:初探物件导向程式设计
Brad Chao
?
計量化交易策略的開發與運用 法人版
計量化交易策略的開發與運用 法人版
derekhcw168
?
藍色投機客 計量化交易策略的開發
藍色投機客 計量化交易策略的開發
guest87f844
?
Java 基本程式設計
Java 基本程式設計
Brad Chao
?
R統計軟體 -安裝與使用
R統計軟體 -安裝與使用
Person Lin
?
Hadoop, the Apple of Our Eyes (這些年,我們一起追的 Hadoop)
Hadoop, the Apple of Our Eyes (這些年,我們一起追的 Hadoop)
Kuo-Chun Su
?
程式交易經驗分享系列(4) 下單機設定及系列回顧
程式交易經驗分享系列(4) 下單機設定及系列回顧
Philip Zheng
?
程式交易經驗分享系列(3) 策略最佳化及wfa法
程式交易經驗分享系列(3) 策略最佳化及wfa法
Philip Zheng
?
程式交易經驗分享系列(2) 交易策略開發步驟
程式交易經驗分享系列(2) 交易策略開發步驟
Philip Zheng
?
程式交易經驗分享系列(1) 程式交易簡介及條件
程式交易經驗分享系列(1) 程式交易簡介及條件
Philip Zheng
?
Trading bot演算法與軟工在程式交易上的實踐
Trading bot演算法與軟工在程式交易上的實踐
Philip Zheng
?

More from koji lin (17)

サーバーサイドでの非同期処理で色々やったよ
サーバーサイドでの非同期処理で色々やったよ
koji lin
?
G1GC
G1GC
koji lin
?
Using armeria to write your RPC
Using armeria to write your RPC
koji lin
?
Annotation processing and code gen
Annotation processing and code gen
koji lin
?
Jcconf
Jcconf
koji lin
?
Use Lambdas in Android
Use Lambdas in Android
koji lin
?
docker intro
docker intro
koji lin
?
Java8 stream
Java8 stream
koji lin
?
Java8 lambda
Java8 lambda
koji lin
?
Idea13
Idea13
koji lin
?
CompletableFuture
CompletableFuture
koji lin
?
Raspberry Pi with Java
Raspberry Pi with Java
koji lin
?
Services you can use to monitor and analyze mobile app
Services you can use to monitor and analyze mobile app
koji lin
?
Programming with Threads in Java
Programming with Threads in Java
koji lin
?
JQuery
JQuery
koji lin
?
山頂洞人日記 - 回歸到最純樸的開發
山頂洞人日記 - 回歸到最純樸的開發
koji lin
?
Android Location-based應用開發分享
Android Location-based應用開發分享
koji lin
?
サーバーサイドでの非同期処理で色々やったよ
サーバーサイドでの非同期処理で色々やったよ
koji lin
?
Using armeria to write your RPC
Using armeria to write your RPC
koji lin
?
Annotation processing and code gen
Annotation processing and code gen
koji lin
?
Use Lambdas in Android
Use Lambdas in Android
koji lin
?
CompletableFuture
CompletableFuture
koji lin
?
Raspberry Pi with Java
Raspberry Pi with Java
koji lin
?
Services you can use to monitor and analyze mobile app
Services you can use to monitor and analyze mobile app
koji lin
?
Programming with Threads in Java
Programming with Threads in Java
koji lin
?
山頂洞人日記 - 回歸到最純樸的開發
山頂洞人日記 - 回歸到最純樸的開發
koji lin
?
Android Location-based應用開發分享
Android Location-based應用開發分享
koji lin
?
Ad

Java8 time