All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.gsonfire.util.RFC3339DateFormat Maven / Gradle / Ivy

Go to download

A java library that adds some very useful features to Gson, like Date serializing to unix timestamp or RFC3339, method (getter) serialization, pre and post processors and many more. Check out the documentation to learn how to use it!

There is a newer version: 1.9.0
Show newest version
package io.gsonfire.util;

import java.text.*;
import java.util.Date;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @autor: julio
 */
public final class RFC3339DateFormat extends DateFormat {

    private static final Pattern TIMEZONE_PATTERN = Pattern.compile("(.*)([+-][0-9][0-9])\\:?([0-9][0-9])$");
    private static final Pattern MILLISECONDS_PATTERN = Pattern.compile("(.*)\\.([0-9]{1,3})([0-9])*(.*)");
    private static final Pattern DATE_ONLY_PATTERN = Pattern.compile("^[0-9]{1,4}-[0-1][0-9]-[0-3][0-9]$");

    private final SimpleDateFormat rfc3339Parser = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
    private final SimpleDateFormat rfc3339Formatter;
    private final boolean serializeTime;

    public RFC3339DateFormat(TimeZone serializationTimezone, boolean serializeTime) {
        if(serializeTime) {
            this.rfc3339Formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
        } else {
            this.rfc3339Formatter = new SimpleDateFormat("yyyy-MM-dd");
        }
        this.serializeTime = serializeTime;
        this.rfc3339Formatter.setTimeZone(serializationTimezone);
    }

    public RFC3339DateFormat(TimeZone serializationTimezone) {
        this(serializationTimezone, true);
    }

    public RFC3339DateFormat(boolean serializeTime) {
        this(TimeZone.getTimeZone("UTC"), serializeTime);
    }

    public RFC3339DateFormat() {
        this(true);
    }

    private String generateTimezone(long time, TimeZone serializationTimezone){
        if(serializationTimezone.getOffset(time) == 0){
            return "Z";
        }

        int offset = (int) (serializationTimezone.getOffset(time) / 1000L);
        int hours = offset / 3600;
        int minutes = Math.abs((offset - hours * 3600) / 60);
        String sign = hours >= 0 ? "+" : "-";

        return sign + String.format("%02d", Math.abs(hours)) + ":" + String.format("%02d", minutes);
    }

    @Override
    public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) {

        StringBuffer formatted = new StringBuffer();

        formatted.append(rfc3339Formatter.format(date).toString());

        if(this.serializeTime) {
            //Add milliseconds
            long time = date.getTime();
            long millis = time % 1000L;
            if(millis > 0){
                String fraction = String.format("%03d", millis);
                formatted.append("." + fraction);
            }

            //Timezone
            String timezoneStr = generateTimezone(time, this.rfc3339Formatter.getTimeZone());
            formatted.append(timezoneStr);
        }
        return formatted;
    }

    @Override
    public Date parse(String source, ParsePosition pos) {
        //Check if this is only a date
        if(DATE_ONLY_PATTERN.matcher(source).matches()) {
            source += "T00:00:00-0000";
        } else {
            if(source.charAt(10) == 't') {
                source = source.substring(0, 10) + "T" + source.substring(12);
            }
        }

        //Filter milliseconds
        long millis = 0;
        if(source.contains(".")){
            Matcher matcher = MILLISECONDS_PATTERN.matcher(source);
            String millisStr = matcher.replaceAll("$2");
            int millisSize = millisStr.length();

            millis = Long.parseLong(millisStr);

            if (millisSize - 3 < 0) {
                millis = (long) (millis * Math.pow(10, 3 - millisSize));
            }

            source = matcher.replaceAll("$1") + matcher.replaceAll("$4");
        }

        //Filter ending in Z
        if(source.endsWith("Z") || source.endsWith("z")){
            source = source.substring(0, source.length() -1) + "-0000";
        } else {
            //Check if we have timezone information present
            Matcher matcher = TIMEZONE_PATTERN.matcher(source);
            if (matcher.matches()) {
                //Filter colon in timezone
                source = matcher.replaceAll("$1") + matcher.replaceAll("$2") + matcher.replaceAll("$3");
            } else {
                //It appears we don't have any timezone info or Z at the end of the date
                //We will assume it is RFC3339
                source += "-0000";
            }
        }

        try {
            Date res = rfc3339Parser.parse(source);
            if(millis > 0){
                res = new Date(res.getTime() + millis);
            }
            pos.setIndex(source.length());
            return res;
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy