自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Java 時間與日期處理

開發(fā) 開發(fā)工具
GMT 即「格林威治標準時間」( Greenwich Mean Time,簡稱 G.M.T. ),指位于英國倫敦郊區(qū)的皇家格林威治天文臺的標準時間,因為本初子午線被定義為通過那里的經(jīng)線。然而由于地球的不規(guī)則自轉(zhuǎn),導(dǎo)致 GMT 時間有誤差,因此目前已不被當作標準時間使用。

[[198241]]

Java 時間與日期處理 從屬于筆者的現(xiàn)代 Java 開發(fā)系列文章,涉及到的引用資料聲明在Java 學(xué)習與實踐資料索引中。

Java 時間與日期處理

在 Java 8 之前,我們最常見的時間與日期處理相關(guān)的類就是 Date、Calendar 以及 SimpleDateFormatter 等等。不過 java.util.Date 也是被詬病已久,它包含了日期、時間、毫秒數(shù)等眾多繁雜的信息,其內(nèi)部利用午夜 12 點來區(qū)分日期,利用 1970-01-01 來計算時間;并且其月份從 0 開始計數(shù),而且用于獲得年、月、日等信息的接口也是太不直觀。除此之外,java.util.Date與 SimpleDateFormatter 都不是類型安全的,而 JSR-310 中的 LocalDate 與 LocalTime 等則是不變類型,更加適合于并發(fā)編程。JSR 310 實際上有兩個日期概念。第一個是 Instant,它大致對應(yīng)于 java.util.Date 類,因為它代表了一個確定的時間點,即相對于標準 Java 紀元(1970年1月1日)的偏移量;但與 java.util.Date 類不同的是其精確到了納秒級別。另一個則是 LocalDate、LocalTime 以及 LocalDateTime 這樣代表了一般時區(qū)概念、易于理解的對象。

Class / TypeDescriptionYearRepresents a year.YearMonthA month within a specific year.LocalDateA date without an explicitly specified time zone.LocalTimeA time without an explicitly specified time zone.LocalDateTimeA combination date and time without an explicitly specified time zone.

最新 JDBC 映射將把數(shù)據(jù)庫的日期類型和 Java 8 的新類型關(guān)聯(lián)起來:

SQLJavadateLocalDatetimeLocalTimetimestampLocalDateTimedatetimeLocalDateTime

時間與日期基礎(chǔ)概念

標準時間

GMT 即「格林威治標準時間」( Greenwich Mean Time,簡稱 G.M.T. ),指位于英國倫敦郊區(qū)的皇家格林威治天文臺的標準時間,因為本初子午線被定義為通過那里的經(jīng)線。然而由于地球的不規(guī)則自轉(zhuǎn),導(dǎo)致 GMT 時間有誤差,因此目前已不被當作標準時間使用。UTC 是最主要的世界時間標準,是經(jīng)過平均太陽時(以格林威治時間 GMT 為準)、地軸運動修正后的新時標以及以「秒」為單位的國際原子時所綜合精算而成的時間。UTC 比 GMT 來得更加精準。其誤差值必須保持在 0.9 秒以內(nèi),若大于 0.9 秒則由位于巴黎的國際地球自轉(zhuǎn)事務(wù)中央局發(fā)布閏秒,使 UTC 與地球自轉(zhuǎn)周期一致。不過日常使用中,GMT 與 UTC 的功能與精確度是沒有差別的。協(xié)調(diào)世界時區(qū)會使用 “Z” 來表示。而在航空上,所有使用的時間劃一規(guī)定是協(xié)調(diào)世界時。而且 Z 在無線電中應(yīng)讀作 “Zulu”(可參見北約音標字母),協(xié)調(diào)世界時也會被稱為 “Zulu time”。

TimeZone&UTC Offsets: 時區(qū)與偏移

人們經(jīng)常會把時區(qū)與 UTC 偏移量搞混,UTC 偏移量代表了某個具體的時間值與 UTC 時間之間的差異,通常用 HH:mm 形式表述。而 TimeZone 則表示某個地理區(qū)域,某個 TimeZone 中往往會包含多個偏移量,而多個時區(qū)可能在一年的某些時間有相同的偏移量。譬如 America/Chicago, America/Denver, 以及 America/Belize 在一年中不同的時間都會包含 -06:00 這個偏移。

時間戳

Unix 時間戳表示當前時間到 1970 年 1 月 1 日 00:00:00 UTC 對應(yīng)的秒數(shù)。注意,JavaScript 內(nèi)的時間戳指的是當前時間到 1970 年 1 月 1 日 00:00:00 UTC 對應(yīng)的毫秒數(shù),和 Unix 時間戳不是一個概念,后者表示秒數(shù),差了 1000 倍。

時間數(shù)字字符串格式

RFC2822

  1. YYYY/MM/DD HH:MM:SS ± timezone(時區(qū)用4位數(shù)字表示) 
  2.  
  3. // eg 1992/02/12 12:23:22+0800 

ISO 8601

國際標準化組織的國際標準 ISO 8601 是日期和時間的表示方法,全稱為《數(shù)據(jù)存儲和交換形式·信息交換·日期和時間的表示方法》。目前最新為第三版 ISO8601:2004,第一版為 ISO8601:1988,第二版為 ISO8601:2000。年由 4 位數(shù)組成,以公歷公元 1 年為 0001 年,以公元前 1 年為 0000 年,公元前 2 年為 -0001 年,其他以此類推。應(yīng)用其他紀年法要換算成公歷,但如果發(fā)送和接受信息的雙方有共同一致同意的其他紀年法,可以自行應(yīng)用。

  1. YYYY-MM-DDThh:mm:ss ± timezone(時區(qū)用HH:MM表示) 
  2. 1997-07-16T08:20:30Z 
  3. // “Z”表示UTC標準時區(qū),即"00:00",所以這里表示零時區(qū)的`1997年7月16日08時20分30秒` 
  4. //轉(zhuǎn)換成位于東八區(qū)的北京時間則為`1997年7月17日16時20分30秒` 
  5. 1997-07-16T19:20:30+01:00 
  6. // 表示東一區(qū)的1997年7月16日19時20秒30分,轉(zhuǎn)換成UTC標準時間的話是1997-07-16T18:20:30Z 

時間戳

  1. // 利用系統(tǒng)標準時間創(chuàng)建 
  2. Timestamp timestamp = new Timestamp(System.currentTimeMillis()); 
  3.  
  4. // 從 Date 對象中創(chuàng)建 
  5. new Timestamp((new Date()).getTime()); 
  6.  
  7. // 獲取自 1970-01-01 00:00:00 GMT 以來的毫秒數(shù) 
  8. timestamp.getTime(); 

在 Java 8 中,即可以使用 java.time.Instant 來表示自從 1970-01-01T00:00:00Z 之后經(jīng)過的標準時間:

  1. // 基于靜態(tài)函數(shù)創(chuàng)建 
  2. Instant instant = Instant.now(); 
  3.  
  4. // 基于 Date 或者毫秒數(shù)轉(zhuǎn)換 
  5. Instant someInstant = someDate.toInstant(); 
  6. Instant someInstant = Instant.ofEpochMilli(someDate.getTime()); 
  7.  
  8. // 基于 TimeStamp 轉(zhuǎn)換 
  9. Instant instant = timestamp.toInstant(); 
  10.  
  11. // 從 LocalDate 轉(zhuǎn)化而來 
  12. LocalDate.now().atStartOfDay().toInstant(ZoneOffset.UTC) 
  13.  
  14. // 從 LocalDateTime 轉(zhuǎn)化而來 
  15. ldt.atZone(ZoneId.systemDefault()).toInstant(); 
  16.  
  17. // 獲取毫秒 
  18. long timeStampMillis = instant.toEpochMilli(); 
  19.  
  20. // 獲取秒 
  21. long timeStampSeconds = instant.getEpochSecond(); 

Clock 方便我們?nèi)プx取當前的日期與時間。Clock 可以根據(jù)不同的時區(qū)來進行創(chuàng)建,并且可以作為System.currentTimeMillis()的替代。這種指向時間軸的對象即是Instant類。Instants 可以被用于創(chuàng)建java.util.Date對象。

  1. Clock clock = Clock.systemDefaultZone(); 
  2. long millis = clock.millis(); 
  3.  
  4. Instant instant = clock.instant(); 
  5. Date legacyDate = Date.from(instant);   // legacy java.util.Date 

Date

  1. // 默認創(chuàng)建 
  2. Date date0 = new Date(); 
  3.  
  4. // 從 TimeStamp 中創(chuàng)建 
  5. Date date1 = new Date(time); 
  6.  
  7. // 基于 Instant 創(chuàng)建 
  8. Date date = Date.from(instant); 
  9.  
  10. // 從格式化字符串中獲取 
  11. SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd"); 
  12. java.util.Date dt=sdf.parse("2005-2-19"); 
  13.  
  14. // 從 LocalDateTime 中轉(zhuǎn)化而來 
  15. Date out = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant()); 

基于 Date 的日期比較常常使用以下方式:

  • 使用 getTime() 方法獲取兩個日期(自1970年1月1日經(jīng)歷的毫秒數(shù)值),然后比較這兩個值。
  • 使用方法 before(),after() 和 equals()。例如,一個月的12號比18號早,則 new Date(99, 2, 12).before(new Date (99, 2, 18)) 返回true。
  • 使用 compareTo() 方法,它是由 Comparable 接口定義的,Date 類實現(xiàn)了這個接口。

Calendar

Date 用于記錄某一個含日期的、精確到毫秒的時間。重點在代表一剎那的時間本身。 Calendar 用于將某一日期放到歷法中的互動——時間和年、月、日、星期、上午、下午、夏令時等這些歷法規(guī)定互相作用關(guān)系和互動。我們可以通過 Calendar 內(nèi)置的構(gòu)造器來創(chuàng)建實例:

  1. Calendar.Builder builder =new Calendar.Builder(); 
  2. Calendar calendar1 = builder.build(); 
  3. Date date = calendar.getTime(); 

在 Calendar 中我們則能夠獲得較為直觀的年月日信息:

  1. // 2017,不再是 2017 - 1900 = 117 
  2. int year =calendar.get(Calendar.YEAR); 
  3.  
  4. int month=calendar.get(Calendar.MONTH)+1; 
  5.  
  6. int day =calendar.get(Calendar.DAY_OF_MONTH); 
  7.  
  8. int hour =calendar.get(Calendar.HOUR_OF_DAY); 
  9.  
  10. int minute =calendar.get(Calendar.MINUTE); 
  11.  
  12. int seconds =calendar.get(Calendar.SECOND);     

除此之外,Calendar 還提供了一系列 set 方法來允許我們動態(tài)設(shè)置時間,還可以使用 add 等方法進行日期的加減。

SimpleDateFormat

SimpleDateFormat 用來進行簡單的數(shù)據(jù)格式化轉(zhuǎn)化操作:

  1. Date dNow = new Date( );  
  2. SimpleDateFormat ft = new SimpleDateFormat ("E yyyy.MM.dd 'at' hh:mm:ss a zzz"); 

LocalDateTime

LocalDate

  1. // 取當前日期: 
  2. LocalDate today = LocalDate.now(); 
  3.  
  4. // 根據(jù)年月日取日期,12月就是12: 
  5. LocalDate crischristmas = LocalDate.of(2017, 5, 15);  
  6.  
  7. // 根據(jù)指定格式字符串取 
  8. LocalDate endOfFeb = LocalDate.parse("2017-05-15"); // 嚴格按照ISO yyyy-MM-dd驗證,02寫成2都不行,當然也有一個重載方法允許自己定義格式 
  9. LocalDate.parse("2014-02-29"); // 無效日期無法通過:DateTimeParseException: Invalid date 
  10.  
  11. // 通過自定義時間字符串格式獲取 
  12. DateTimeFormatter germanFormatter = 
  13.     DateTimeFormatter 
  14.         .ofLocalizedDate(FormatStyle.MEDIUM) 
  15.         .withLocale(Locale.GERMAN); 
  16.  
  17. LocalDate xmas = LocalDate.parse("24.12.2014", germanFormatter); 
  18. System.out.println(xmas);   // 2014-12-24 
  19.  
  20. // 獲取其他時區(qū)下日期 
  21. LocalDate localDate = LocalDate.now(ZoneId.of("GMT+02:30")); 
  22.  
  23. // 從 LocalDateTime 中獲取實例 
  24. LocalDateTime localDateTime = LocalDateTime.now(); 
  25. LocalDate localDate = localDateTime.toLocalDate(); 

日期操作

  1. // 取本月第1天 
  2. LocalDate firstDayOfThisMonth = today.with(TemporalAdjusters.firstDayOfMonth()); // 2014-12-01 
  3.  
  4. // 取本月第2天 
  5. LocalDate secondDayOfThisMonth = today.withDayOfMonth(2); // 2014-12-02 
  6.  
  7. // 取本月最后一天,再也不用計算是28,29,30還是31 
  8. LocalDate lastDayOfThisMonth = today.with(TemporalAdjusters.lastDayOfMonth()); // 2014-12-31 
  9.  
  10. // 取下一天 
  11. LocalDate firstDayOf2015 = lastDayOfThisMonth.plusDays(1); // 變成了2015-01-01 
  12.  
  13. // 取2015年1月第一個周一 
  14. LocalDate firstMondayOf2015 = LocalDate.parse("2015-01-01").with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)); // 2015-01-05 

LocalTime

  1. // 獲取其他時區(qū)下時間 
  2. LocalTime localTime = LocalTime.now(ZoneId.of("GMT+02:30")); 
  3.  
  4. // 從 LocalDateTime 中獲取實例 
  5. LocalDateTime localDateTime = LocalDateTime.now(); 
  6. LocalTime localTime = localDateTime.toLocalTime(); 
  7.  
  8.  
  9. - 12:00 
  10. - 12:01:02 
  11. - 12:01:02.345 

LocalDateTime

  1. // 通過時間戳創(chuàng)建 
  2. LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochSecond(1450073569l), TimeZone.getDefault().toZoneId()); 
  3.  
  4. // 通過 Date 對象創(chuàng)建 
  5. Date in = new Date(); 
  6. LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault()); 
  7.  
  8. // 通過解析時間字符串創(chuàng)建 
  9. DateTimeFormatter formatter = 
  10.     DateTimeFormatter 
  11.         .ofPattern("MMM dd, yyyy - HH:mm"); 
  12.  
  13. LocalDateTime parsed = LocalDateTime.parse("Nov 03, 2014 - 07:13", formatter); 
  14. String string = formatter.format(parsed); 
  15. System.out.println(string);     // Nov 03, 2014 - 07:13 
  • 獲取年、月、日等信息
  1. LocalDateTime sylvester = LocalDateTime.of(2014, Month.DECEMBER, 31, 23, 59, 59); 
  2.  
  3. DayOfWeek dayOfWeek = sylvester.getDayOfWeek(); 
  4. System.out.println(dayOfWeek);      // WEDNESDAY 
  5.  
  6. Month month = sylvester.getMonth(); 
  7. System.out.println(month);          // DECEMBER 
  8.  
  9. long minuteOfDay = sylvester.getLong(ChronoField.MINUTE_OF_DAY); 
  10. System.out.println(minuteOfDay);    // 1439 
  • 時間格式化展示
  1. DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); 
  2. LocalDateTime dateTime = LocalDateTime.of(1986, Month.APRIL, 8, 12, 30); 
  3. String formattedDateTime = dateTime.format(formatter); // "1986-04-08 12:30" 

時間操作

  1. localDateTime.plusDays(1); 
  2. localDateTime.minusHours(2); 

時區(qū)轉(zhuǎn)換

  1. System.out.println(ZoneId.getAvailableZoneIds()); 
  2. // prints all available timezone ids 
  3.  
  4. ZoneId zone1 = ZoneId.of("Europe/Berlin"); 
  5. ZoneId zone2 = ZoneId.of("Brazil/East"); 
  6. System.out.println(zone1.getRules()); 
  7. System.out.println(zone2.getRules()); 
  8.  
  9. // ZoneRules[currentStandardOffset=+01:00] 
  10. // ZoneRules[currentStandardOffset=-03:00] 
  11. LocalDateTime ldt = ... 
  12. ZonedDateTime zdt = ldt.atZone(ZoneId.systemDefault()); 
  13. Date output = Date.from(zdt.toInstant()); 
  14. ZoneId losAngeles = ZoneId.of("America/Los_Angeles"); 
  15. ZoneId berlin = ZoneId.of("Europe/Berlin"); 
  16.  
  17. // 2014-02-20 12:00 
  18. LocalDateTime dateTime = LocalDateTime.of(2014, 02, 20, 12, 0); 
  19.  
  20. // 2014-02-20 12:00, Europe/Berlin (+01:00) 
  21. ZonedDateTime berlinDateTime = ZonedDateTime.of(dateTime, berlin); 
  22.  
  23. // 2014-02-20 03:00, America/Los_Angeles (-08:00) 
  24. ZonedDateTime losAngelesDateTime = berlinDateTime.withZoneSameInstant(losAngeles); 
  25.  
  26. int offsetInSeconds = losAngelesDateTime.getOffset().getTotalSeconds(); // -28800 
  27.  
  28. // a collection of all available zones 
  29. Set<String> allZoneIds = ZoneId.getAvailableZoneIds(); 
  30.  
  31. // using offsets 
  32. LocalDateTime date = LocalDateTime.of(2013, Month.JULY, 20, 3, 30); 
  33. ZoneOffset offset = ZoneOffset.of("+05:00"); 
  34.  
  35. // 2013-07-20 03:30 +05:00 
  36. OffsetDateTime plusFive = OffsetDateTime.of(date, offset); 
  37.  
  38. // 2013-07-19 20:30 -02:00 
  39. OffsetDateTime minusTwo = plusFive.withOffsetSameInstant(ZoneOffset.ofHours(-2)); 

時差

Period 類以年月日來表示日期差,而 Duration 以秒與毫秒來表示時間差;Duration 適用于處理 Instant 與機器時間。

  1. // periods 
  2.  
  3. LocalDate firstDate = LocalDate.of(2010, 5, 17); // 2010-05-17 
  4. LocalDate secondDate = LocalDate.of(2015, 3, 7); // 2015-03-07 
  5. Period period = Period.between(firstDate, secondDate); 
  6.  
  7. int days = period.getDays(); // 18 
  8. int months = period.getMonths(); // 9 
  9. int years = period.getYears(); // 4 
  10. boolean isNegative = period.isNegative(); // false 
  11.  
  12. Period twoMonthsAndFiveDays = Period.ofMonths(2).plusDays(5); 
  13. LocalDate sixthOfJanuary = LocalDate.of(2014, 1, 6); 
  14.  
  15. // add two months and five days to 2014-01-06, result is 2014-03-11 
  16. LocalDate eleventhOfMarch = sixthOfJanuary.plus(twoMonthsAndFiveDays); 
  17.  
  18.  
  19. // durations 
  20.  
  21. Instant firstInstant= Instant.ofEpochSecond( 1294881180 ); // 2011-01-13 01:13 
  22. Instant secondInstant = Instant.ofEpochSecond(1294708260); // 2011-01-11 01:11 
  23.  
  24. Duration between = Duration.between(firstInstant, secondInstant); 
  25.  
  26. // negative because firstInstant is after secondInstant (-172920) 
  27. long seconds = between.getSeconds(); 
  28.  
  29. // get absolute result in minutes (2882) 
  30. long absoluteResult = between.abs().toMinutes(); 
  31.  
  32. // two hours in seconds (7200) 
  33. long twoHoursInSeconds = Duration.ofHours(2).getSeconds(); 

 【本文是51CTO專欄作者“張梓雄 ”的原創(chuàng)文章,如需轉(zhuǎn)載請通過51CTO與作者聯(lián)系】

戳這里,看該作者更多好文

 

責任編輯:武曉燕 來源: 51CTO專欄
相關(guān)推薦

2024-02-22 14:51:38

Java字符串

2010-03-31 18:47:08

Oracle時間

2010-04-29 12:23:58

Oracle 獲取系統(tǒng)

2021-01-18 07:43:12

JavaGMTUTC

2010-07-19 15:37:48

Perl日期時間

2024-01-19 07:39:25

Go日期開發(fā)

2023-09-18 11:32:37

Python計算

2009-07-27 13:46:48

ASP.NET編程日期與時間的處理

2022-04-13 10:38:04

Springboot日期時間格式化

2024-06-25 08:26:51

高效日期計算安全

2025-04-18 10:21:43

JavaScript開發(fā)Date

2024-01-11 18:04:53

SQL數(shù)據(jù)庫

2014-12-22 10:14:31

Java8

2012-03-27 09:20:57

Java

2010-09-14 14:22:30

Sql Server日

2010-05-27 13:26:20

MySQL日期時間函數(shù)

2024-12-17 18:17:13

Python開發(fā)

2023-11-17 09:50:38

云原生監(jiān)控

2010-04-01 10:29:12

Oracle 處理日期

2020-12-01 07:18:35

Java8日期時間
點贊
收藏

51CTO技術(shù)棧公眾號