1. 程式人生 > >根據時間戳轉Date實現(Java)及實現原理分析

根據時間戳轉Date實現(Java)及實現原理分析

時間戳是指格林威治時間1970年01月01日00時00分00秒(北京時間1970年01月01日08時00分00秒)起至現在的總秒數。

本次實現跟根據Java.text.* 包中的工具類實現的,示例程式碼:

import java.text.SimpleDateFormat;

public class TestTimestemp {
	public static void main(String[] args) {
		SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
		long currentTimeMillis = System.currentTimeMillis();
		System.out.println(currentTimeMillis); // 1540034763419
		String format = sf.format(currentTimeMillis);//1540034763419
		System.out.println(format); //2018-10-20
	}
}

以下是對原始碼簡單分析的筆記:

1. 先看SimpleDateFormat的類繼承關係

public class SimpleDateFormat extends DateFormat {...}
public abstract class DateFormat extends Format {...}
public abstract class Format implements Serializable, Cloneable {...}

2. 上面sf.format()呼叫的是Format類中的方法,最終其實呼叫的是抽象方法,原始碼如下:

public abstract class Format implements Serializable, Cloneable {

    public final String format (Object obj) {
        return format(obj, new StringBuffer(), new FieldPosition(0)).toString();
    }

    public abstract StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos);
}

3. Format中的抽象方法的實現類在DateFormat中,DateFormat最終呼叫的也是抽象方法,原始碼如下:

public abstract class DateFormat extends Format {
    public final StringBuffer format(Object obj, StringBuffer toAppendTo,
                                     FieldPosition fieldPosition)
    {
        if (obj instanceof Date)
            return format( (Date)obj, toAppendTo, fieldPosition );
        else if (obj instanceof Number)
            return format( new Date(((Number)obj).longValue()),
                          toAppendTo, fieldPosition );
        else
            throw new IllegalArgumentException("Cannot format given Object as a Date");
    }
    
    public abstract StringBuffer format(Date date, StringBuffer toAppendTo, 
                                            FieldPosition fieldPosition);
}

4. DateFormat中的抽象方法實現類在SimpleDateFormat中,具體的轉換演算法也是在該類中實現,原始碼如下:

public class SimpleDateFormat extends DateFormat {
    protected Calendar calendar;//建立SimpleDateFormat物件時會例項化該物件,具體方法可查原始碼

    @Override
    public StringBuffer format(Date date, StringBuffer toAppendTo,
                               FieldPosition pos)
    {
        pos.beginIndex = pos.endIndex = 0;
        return format(date, toAppendTo, pos.getFieldDelegate());
    }

    // 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;
    }
}