成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

在Java中,你真的會(huì)日期轉(zhuǎn)換嗎

lscho / 1999人閱讀

摘要:什么是在對(duì)的解釋如下是一個(gè)用來對(duì)位置敏感的格式化和解析日期的實(shí)體類。他允許把日期格式化成,把解析成日期和規(guī)范化。

1.什么是SimpleDateFormat

在java doc對(duì)SimpleDateFormat的解釋如下:

SimpleDateFormat is a concrete class for formatting and parsing dates in a locale-sensitive manner. It allows for formatting
(date → text), parsing (text → date), and normalization.

SimpleDateFormat是一個(gè)用來對(duì)位置敏感的格式化和解析日期的實(shí)體類。他允許把日期格式化成text,把text解析成日期和規(guī)范化。

1.1使用SimpleDateFormat

simpleDateFormat的使用方法比較簡(jiǎn)單:

public static void main(String[] args) throws Exception {

 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-mm-dd  HH:mm:ss");

 System.out.println(simpleDateFormat.format(new Date()));

 System.out.println(simpleDateFormat.parse("2018-07-09  11:10:21"));
 }

1.首先需要定義一個(gè)日期的pattern,這里我們定義的是"yyyy-mm-dd HH:mm:ss" ,也就是我們這個(gè)simpleDateFormat不管是格式化還是解析都需要按照這個(gè)pattern。

2.對(duì)于format需要傳遞Date的對(duì)象,會(huì)返回一個(gè)String類型,這個(gè)String會(huì)按照我們上面的格式生成。

3.對(duì)于parse需要傳遞一個(gè)按照上面pattern的字符串,如果傳遞錯(cuò)誤的pattern會(huì)拋出java.text.ParseException異常,如果傳遞正確的會(huì)生成一個(gè)Date對(duì)象。

附:格式占位符

 G 年代標(biāo)志符

 y 年

 M 月

 d 日

 h 時(shí) 在上午或下午 (1~12)

 H 時(shí) 在一天中 (0~23)

 m 分

 s 秒

 S 毫秒

 E 星期

 D 一年中的第幾天

 F 一月中第幾個(gè)星期幾

 w 一年中第幾個(gè)星期

 W 一月中第幾個(gè)星期

 a 上午 / 下午 標(biāo)記符

 k 時(shí) 在一天中 (1~24)

 K 時(shí) 在上午或下午 (0~11)

 z 時(shí)區(qū)
2.SimpleDateFormat的隱患

很多初學(xué)者,或者一些經(jīng)驗(yàn)比較淺的java開發(fā)工程師,用SimpleDateFormat會(huì)出現(xiàn)一些奇奇怪怪的BUG。

1.結(jié)果值不對(duì):轉(zhuǎn)換的結(jié)果值經(jīng)常會(huì)出人意料,和預(yù)期不同,往往讓很多人摸不著頭腦。

2.內(nèi)存泄漏: 由于轉(zhuǎn)換的結(jié)果值不對(duì),后續(xù)的一些操作,如一個(gè)循環(huán),累加一天處理一個(gè)東西,但是生成的日期如果異常導(dǎo)致很大的話,會(huì)讓這個(gè)循環(huán)變成一個(gè)類似死循環(huán)一樣導(dǎo)致系統(tǒng)內(nèi)存泄漏,頻繁觸發(fā)GC,造成系統(tǒng)不可用。

為什么會(huì)出現(xiàn)這么多問題呢?因?yàn)镾impleDateFormat線程不安全,很多人都會(huì)寫個(gè)Util類,然后把SimpleDateFormat定義成全局的一個(gè)常量,所有線程都共享這個(gè)常量:

protected static final SimpleDateFormat dayFormat = new SimpleDateFormat("yyyy-MM-dd");

public static Date formatDate(String date) throws ParseException {

 return dayFormat.parse(date);

}

為什么SimpleDateFormat會(huì)線程不安全呢,在SimpleDateFormat源碼中,所有的格式化和解析都需要通過一個(gè)中間對(duì)象進(jìn)行轉(zhuǎn)換,那就是Calendar,而這個(gè)也是我們出現(xiàn)線程不安全的罪魁禍?zhǔn)?,試想一下?dāng)我們有多個(gè)線程操作同一個(gè)Calendar的時(shí)候后來的線程會(huì)覆蓋先來線程的數(shù)據(jù),那最后其實(shí)返回的是后來線程的數(shù)據(jù),這樣就導(dǎo)致我們上面所述的BUG的產(chǎn)生:

/

/ Called from Format after creating a FieldDelegate

 private StringBuffer format(Date date, StringBuffer toAppendTo,

 FieldDelegate delegate) {

 // Convert input date to time field list

 calendar.setTime(date);

?

 boolean useDateFormatSymbols = useDateFormatSymbols();

?

 for (int i = 0; i < compiledPattern.length; ) {

 int tag = compiledPattern[i] >>> 8;

 int count = compiledPattern[i++] & 0xff;

 if (count == 255) {

 count = compiledPattern[i++] << 16;

 count |= compiledPattern[i++];

 }

?

 switch (tag) {

 case TAG\_QUOTE\_ASCII_CHAR:

 toAppendTo.append((char)count);

 break;

?

 case TAG\_QUOTE\_CHARS:

 toAppendTo.append(compiledPattern, i, count);

 i += count;

 break;

?

 default:

 subFormat(tag, count, delegate, toAppendTo, useDateFormatSymbols);

 break;

 }

 }

 return toAppendTo;

 }

3.如何避坑

對(duì)于SimpleDateFormat的解決方法有下面幾種:

3.1新建SimpleDateFormat

上面出現(xiàn)Bug的原因是因?yàn)樗芯€程都共用一個(gè)SimpleDateFormat,這里有個(gè)比較好解決的辦法,每次使用的時(shí)候都創(chuàng)建一個(gè)新的SimpleDateFormat,我們可以在DateUtils中將創(chuàng)建SimpleDateFormat放在方法內(nèi)部:

public static Date formatDate(String date) throws ParseException {

 SimpleDateFormat dayFormat = new SimpleDateFormat("yyyy-MM-dd");

 return dayFormat.parse(date);

}

上面這個(gè)方法雖然能解決我們的問題但是引入了另外一個(gè)問題就是,如果這個(gè)方法使用量比較大,有可能會(huì)頻繁造成Young gc,整個(gè)系統(tǒng)還是會(huì)受一定的影響。

3.2使用ThreadLocal

使用ThreadLocal能避免上面頻繁的造成Young gc,我們對(duì)每個(gè)線程都使用ThreadLocal進(jìn)行保存,由于ThreadLocal是線程之間隔離開的,所以不會(huì)出現(xiàn)線程安全問題:

private static ThreadLocal simpleDateFormatThreadLocal = new ThreadLocal<>();

 public static Date formatDate(String date) throws ParseException {

 SimpleDateFormat dayFormat = getSimpleDateFormat();

 return dayFormat.parse(date);

 }

?

 private static SimpleDateFormat getSimpleDateFormat() {

 SimpleDateFormat simpleDateFormat = simpleDateFormatThreadLocal.get();

 if (simpleDateFormat == null){

 simpleDateFormat = new SimpleDateFormat("yyyy-mm-dd  HH:mm:ss")

 simpleDateFormatThreadLocal.set(simpleDateFormat);

 }

 return simpleDateFormat;

 }
3.3使用第三方工具包

雖然上面的ThreadLocal能解決我們出現(xiàn)的問題,但是第三方工具包提供的功能更加強(qiáng)大,在java中有兩個(gè)類庫(kù)比較出名一個(gè)是Joda-Time,一個(gè)是Apache common包

3.3.1 Joda-Time(推薦)

Joda-Time 令時(shí)間和日期值變得易于管理、操作和理解。對(duì)于我們復(fù)雜的操作都可以使用Joda-Time操作,下面我列舉兩個(gè)例子,對(duì)于把日期加上90天,如果使用原生的Jdk我們需要這樣寫:

Calendar calendar = Calendar.getInstance();

calendar.set(2000, Calendar.JANUARY, 1, 0, 0, 0);

SimpleDateFormat sdf =

 new SimpleDateFormat("E MM/dd/yyyy HH:mm:ss.SSS");

calendar.add(Calendar.DAY\_OF\_MONTH, 90);

System.out.println(sdf.format(calendar.getTime()));

但是在我們的joda-time中只需要兩句話,并且api也比較通俗易懂,所以你為什么不用Joda-Time呢?

DateTime dateTime = new DateTime(2000, 1, 1, 0, 0, 0, 0);

System.out.println(dateTime.plusDays(90).toString("E MM/dd/yyyy HH:mm:ss.SSS");
3.3.2 common-lang包

在common-lang包中有個(gè)類叫FastDateFormat,由于common-lang這個(gè)包基本被很多Java項(xiàng)目都會(huì)引用,所以你可以不用專門去引用處理時(shí)間包,即可處理時(shí)間,在FastDateFormat中每次處理時(shí)間的時(shí)候會(huì)創(chuàng)建一個(gè)calendar,使用方法比較簡(jiǎn)單代碼如下所示:

FastDateFormat.getInstance().format(new Date());

3.4升級(jí)jdk8(推薦)

在java8中Date這個(gè)類中的很多方法包括構(gòu)造方法都被打上了@Deprecated廢棄的注解,取而代之的是LocalDateTime,LocalDate LocalTime這三個(gè)類:

LocalDate無法包含時(shí)間;

LocalTime無法包含日期;

LocalDateTime才能同時(shí)包含日期和時(shí)間。

如果你是Java8,那你一定要使用他,在日期的格式化和解析方面不用考慮線程安全性,代碼如下:

public static String formatTime(LocalDateTime time,String pattern) {

 return time.format(DateTimeFormatter.ofPattern(pattern));

 }

?

當(dāng)然localDateTime是java8的一大亮點(diǎn),當(dāng)然不僅僅只是解決了線程安全的問題,同樣也提供了一些其他的運(yùn)算比如加減天數(shù):

//日期加上一個(gè)數(shù),根據(jù)field不同加不同值,field為ChronoUnit.*

 public static LocalDateTime plus(LocalDateTime time, long number, TemporalUnit field) {

 return time.plus(number, field);

 }

?

 //日期減去一個(gè)數(shù),根據(jù)field不同減不同值,field參數(shù)為ChronoUnit.*

 public static LocalDateTime minu(LocalDateTime time, long number, TemporalUnit field){

 return time.minus(number,field);

 }

最后,如果你擔(dān)心使用LocalDateTime 會(huì)對(duì)你現(xiàn)有的代碼產(chǎn)生很大的改變的話,那你可以將他們兩進(jìn)行互轉(zhuǎn):

//Date轉(zhuǎn)換為L(zhǎng)ocalDateTime

 public static LocalDateTime convertDateToLDT(Date date) {

 return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());

 }

?

 //LocalDateTime轉(zhuǎn)換為Date

 public static Date convertLDTToDate(LocalDateTime time) {

 return Date.from(time.atZone(ZoneId.systemDefault()).toInstant());

 }
更多技術(shù)福利請(qǐng)掃我的技術(shù)公眾號(hào)
如果你喜歡這篇文章歡迎點(diǎn)贊,轉(zhuǎn)發(fā)??梢話呙韫娞?hào)即可獲得我的1v1 VIP服務(wù)。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://hztianpu.com/yun/76417.html

相關(guān)文章

  • 真的知道Python的字符串怎么用

    摘要:方法可接收兩個(gè)參數(shù),第一個(gè)參數(shù)是分隔符,即用來分隔字符串的字符,默認(rèn)是所有的空字符,包括空格換行制表符等。拆分過程會(huì)消耗分隔符,所以拆分結(jié)果中不包含分隔符。 正如《你真的知道Python的字符串是什么嗎?》所寫,Python 中字符串是由 Uniocde 編碼的字符組成的不可變序列,它具備與其它序列共有的一些操作,例如判斷元素是否存在、拼接序列、切片操作、求長(zhǎng)度、求最值、求元素的索引位...

    scwang90 評(píng)論0 收藏0
  • 真的知道Python的字符串怎么用?

    摘要:方法可接收兩個(gè)參數(shù),第一個(gè)參數(shù)是分隔符,即用來分隔字符串的字符,默認(rèn)是所有的空字符,包括空格換行制表符等。拆分過程會(huì)消耗分隔符,所以拆分結(jié)果中不包含分隔符。 正如《你真的知道Python的字符串是什么嗎?》所寫,Python 中字符串是由 Uniocde 編碼的字符組成的不可變序列,它具備與其它序列共有的一些操作,例如判斷元素是否存在、拼接序列、切片操作、求長(zhǎng)度、求最值、求元素的索引位...

    jifei 評(píng)論0 收藏0
  • Java8實(shí)戰(zhàn)》-第十二章筆記(新的日期和時(shí)間API)

    摘要:合并日期和時(shí)間這個(gè)復(fù)合類名叫,是和的合體。截至目前,我們介紹的這些日期時(shí)間對(duì)象都是不可修改的,這是為了更好地支持函數(shù)式編程,確保線程安全,保持領(lǐng)域模式一致性而做出的重大設(shè)計(jì)決定。 新的日期和時(shí)間API Java的API提供了很多有用的組件,能幫助你構(gòu)建復(fù)雜的應(yīng)用。不過,Java API也不總是完美的。我們相信大多數(shù)有經(jīng)驗(yàn)的程序員都會(huì)贊同Java 8之前的庫(kù)對(duì)日期和時(shí)間的支持就非常不理想...

    khlbat 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<