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

com.github.mygreen.cellformatter.term.DateTerm Maven / Gradle / Ivy

There is a newer version: 0.12
Show newest version
package com.github.mygreen.cellformatter.term;

import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.github.mygreen.cellformatter.lang.Era;
import com.github.mygreen.cellformatter.lang.EraPeriod;
import com.github.mygreen.cellformatter.lang.EraResolver;
import com.github.mygreen.cellformatter.lang.ExcelDateUtils;
import com.github.mygreen.cellformatter.lang.MSLocale;
import com.github.mygreen.cellformatter.lang.MessageResolver;
import com.github.mygreen.cellformatter.lang.Utils;


/**
 * 日時の書式の項
 * 
 * @version 0.5
 * @author T.TSUCHIE
 *
 */
public abstract class DateTerm implements Term {
    
    protected static final Logger logger = LoggerFactory.getLogger(DateTerm.class);
    
    protected static final MessageResolver messageResolver = new MessageResolver("com.github.mygreen.cellformatter.label");
    
    protected static final EraResolver eraResolver = new EraResolver();
    
    @Override
    public String format(Calendar value, MSLocale formatLocale, Locale runtimeLocale) {
        // このメソッドは実質呼ばれない。
        return format(value, formatLocale, runtimeLocale, false);
    }
    
    /**
     * 値をフォーマットする。
     * @param value フォーマット対象の値。
     * @param formatLocale 書式中に指定されたロケール。
     * @param runtimeLocale 実行時にしていされたロケール。
     * @param isStartDate1904 日時が1904年始まりかどうか。
     * @return フォーマットされた文字列。nullは返さない。
     */
    public abstract String format(Calendar value, MSLocale formatLocale, Locale runtimeLocale, boolean isStartDate1904);
    
    /**
     * 経過時間を計算するときの基準日を取得する。
     * ・1900/2/28までは、-1日ずれる。Excelは1900年は1月0日(=1899年12月31日)から始まるため、1日多い。
     * ・1900/3/1以降は、-2日ずれず。Excel は、閏日ではない1900年2月29日(=1900年3月1日)が存在するため1日多い。
     * @param date
     * @param isStartDate1904
     * @return
     */
    private static long getElapsedZeroTime(final Date date, final boolean isStartDate1904) {
        
        if(isStartDate1904) {
            return ExcelDateUtils.getExcelZeroDateTime(isStartDate1904);
        } else {
            if(ExcelDateUtils.MILLISECONDS_19000301 <= date.getTime()) {
                // 1900-03-01以降
                return ExcelDateUtils.MILLISECONDS_19000101 - TimeUnit.DAYS.toMillis(2);
            } else {
                return ExcelDateUtils.MILLISECONDS_19000101 - TimeUnit.DAYS.toMillis(1);
            }
        }
        
    }
    
    /**
     * [h] - 24時を超える経過時間の処理
     */
    public static DateTerm elapsedHour(final String format) {
        return new ElapsedHourTerm(format);
    }
    
    
    /**
     * [m] - 60分を超える経過時間の処理
     */
    public static DateTerm elapsedMinute(final String format) {
        return new ElapsedMinuteTerm(format);
    }
    
    /**
     * [s] - 60秒を超える経過時間の処理
     */
    public static DateTerm elapsedSecond(final String format) {
        return new ElapsedSecondTerm(format);
    }
    
    /**
     * y - 年の場合の処理
     */
    public static DateTerm year(final String format) {
        return new YearTerm(format);
    }
    
    /**
     * g - 元号の名称の場合の処理
     */
    public static DateTerm eraName(final String format) {
        return new EraNameTerm(format);
    }
    
    /**
     * e - 元号の年の場合の処理
     */
    public static DateTerm eraYear(final String format) {
        return new EraYearTerm(format);
    }
    
    /**
     * r - 元号の名称と年の場合の処理
     */
    public static DateTerm eraNameYear(final String format) {
        return new EraNameYearTerm(format);
    }
    
    /**
     * m - 月の場合の処理
     */
    public static DateTerm month(final String format) {
        return new MonthTerm(format);
    }
    
    /**
     * d - 日の場合の処理
     */
    public static DateTerm day(final String format) {
        return new DayTerm(format);
    }
    
    /**
     * a - 曜日の名称場合の処理
     */
    public static DateTerm weekName(final String format) {
        return new WeekName(format);
    }
    
    /**
     * n - 曜日の名称場合の処理(OpenOffice用)
     */
    public static DateTerm weekNameForOO(final String format) {
        return new WeekNameForOO(format);
    }
    
    /**
     * ww - 年の週番号(OpenOffice用)
     */
    public static DateTerm weekNumber(final String format) {
        return new WeekNumberTerm(format);
    }
    
    /**
     * h - 時間の場合の処理
     * @param format
     * @param half 12時間表示かどうか
     */
    public static DateTerm hour(final String format, final boolean half) {
        return new HourTerm(format, half);
    }
    
    /**
     * m - 分の場合の処理
     */
    public static DateTerm minute(final String format) {
        return new MinuteTerm(format);
    }
    
    /**
     * s - 秒の場合の処理
     */
    public static DateTerm second(final String format) {
        return new SecondTerm(format);
    }
    
    /**
     * q - 四半期の場合の処理(OpenOffice用)
     */
    public static DateTerm quater(final String format) {
        return new QuaterTerm(format);
    }
    
    /**
     * AM/PM - 午前/午後の場合の処理
     */
    public static DateTerm amPm(final String format) {
        return new AmPmTerm(format);
    }
    
    /**
     * [h] - 24時を超える経過時間の処理
     */
    public static class ElapsedHourTerm extends DateTerm {
        
        /** ミリ秒を時間に直すための基底 */
        private static final long BASE = 1000*60*60;
        
        private final String format;
        
        public ElapsedHourTerm(final String format) {
            this.format = format;
        }
        
        @Override
        public String format(final Calendar cal, final MSLocale formatLocale, final Locale runtimeLocale, final boolean isStartDate1904) {
            
            final long zeroTime = getElapsedZeroTime(cal.getTime(), isStartDate1904);
            if(logger.isInfoEnabled()) {
                logger.info("ElapsedHour:calendar={}, zeroTime={}.", ExcelDateUtils.formatDate(cal.getTime()), ExcelDateUtils.formatDate(new Date(zeroTime)));
            }
            
            final long time = (long) ((cal.getTime().getTime() - zeroTime) / BASE);
            final int formatLength = format.length();
            return Utils.supplyZero(String.valueOf(time), formatLength);
        }
        
        public String getFormat() {
            return format;
        }
        
    }
    
    /**
     * [m] - 60分を超える経過時間の処理
     */
    public static class ElapsedMinuteTerm extends DateTerm {
        
        /** ミリ秒を分に直すための基底 */
        private static final long BASE = 1000*60;
        
        private final String format;
        
        public ElapsedMinuteTerm(final String format) {
            this.format = format;
        } 
        
        @Override
        public String format(final Calendar cal, final MSLocale formatLocale, final Locale runtimeLocale, final boolean isStartDate1904) {
            
            final long zeroTime = getElapsedZeroTime(cal.getTime(), isStartDate1904);
            if(logger.isInfoEnabled()) {
                logger.info("ElapsedMinute:calendar={}, zeroTime={}.", ExcelDateUtils.formatDate(cal.getTime()), ExcelDateUtils.formatDate(new Date(zeroTime)));
            }
            
            final long time = (long) ((cal.getTime().getTime() - zeroTime) / BASE);
            final int formatLength = format.length();
            return Utils.supplyZero(String.valueOf(time), formatLength);
        }
        
        public String getFormat() {
            return format;
        }
        
    }
    
    /**
     * [s] - 60秒を超える経過時間の処理
     */
    public static class ElapsedSecondTerm extends DateTerm {
        
        /** ミリ秒を秒に直すための基底 */
        private static final long BASE = 1000;
        
        private final String format;
        
        public ElapsedSecondTerm(final String format) {
            this.format = format;
        } 
        
        @Override
        public String format(final Calendar cal, final MSLocale formatLocale, final Locale runtimeLocale, final boolean isStartDate1904) {
            
            final long zeroTime = getElapsedZeroTime(cal.getTime(), isStartDate1904);
            if(logger.isInfoEnabled()) {
                logger.info("ElapsedSecond:calendar={}, zeroTime={}.", ExcelDateUtils.formatDate(cal.getTime()), ExcelDateUtils.formatDate(new Date(zeroTime)));
            }
            
            final long time = (long) ((cal.getTime().getTime() - zeroTime) / BASE);
            final int formatLength = format.length();
            return Utils.supplyZero(String.valueOf(time), formatLength);
        }
        
        public String getFormat() {
            return format;
        }
        
    }
    
    /**
     * y - 年の場合
     */
    public static class YearTerm extends DateTerm {
        
        private final String format;
        
        public YearTerm(final String format) {
            this.format = format;
        } 
        
        @Override
        public String format(final Calendar cal, final MSLocale formatLocale, final Locale runtimeLocale, final boolean isStartDate1904) {
            
            final String value = String.valueOf(cal.get(Calendar.YEAR));
            final int formatLength = format.length();
            
            // 2桁、4桁補正する
            if(formatLength <= 2) {
                return Utils.supplyZero(value, 2).substring(2);
            } else {
                return Utils.supplyZero(value, 4);
            }
        }
        
        public String getFormat() {
            return format;
        }
        
    }
    
    /**
     * g - 元号の名称の場合
     */
    public static class EraNameTerm extends DateTerm {
        
        private final String format;
        
        public EraNameTerm(final String format) {
            this.format = format;
        } 
        
        @Override
        public String format(final Calendar cal, final MSLocale formatLocale, final Locale runtimeLocale, final boolean isStartDate1904) {
            
            final Date date = cal.getTime();
            
            final Era era;
            if(formatLocale != null) {
                era = eraResolver.getEra(formatLocale);
            } else {
                era = eraResolver.getEra(runtimeLocale);
            }
            
            if(era.isUnkndown()) {
                return "";
            }
            
            final EraPeriod period = era.getTargetPeriod(date);
            if(period.isUnknown()) {
                return "";
            }
            
            final int formatLength = format.length();
            if(formatLength == 1) {
                return period.getAbbrevRomanName();
                
            } else if(formatLength == 2) {
                return period.getAbbrevName();
                
            } else {
                return period.getName();
            }
        }
        
        public String getFormat() {
            return format;
        }
        
    }
    
    /**
     * e - 元号の年の場合
     */
    public static class EraYearTerm extends DateTerm {
        
        private final String format;
        
        public EraYearTerm(final String format) {
            this.format = format;
        } 
        
        @Override
        public String format(final Calendar cal, final MSLocale formatLocale, final Locale runtimeLocale, final boolean isStartDate1904) {
            
            final int formatLength = format.length();
            final Date date = cal.getTime();
            
            final Era era;
            if(formatLocale != null) {
                era = eraResolver.getEra(formatLocale);
            } else {
                era = eraResolver.getEra(runtimeLocale);
            }
            
            if(era.isUnkndown()) {
                // 該当する時代の定義がない場合
                String value = String.valueOf(cal.get(Calendar.YEAR));
                return Utils.supplyZero(value, formatLength);
            }
            
            final EraPeriod period = era.getTargetPeriod(date);
            if(period.isUnknown()) {
                // 期間が不明な場合
                String value = String.valueOf(cal.get(Calendar.YEAR));
                return Utils.supplyZero(value, formatLength);
                
            }
            
            final String value = String.valueOf(period.getEraYear(cal));
            return Utils.supplyZero(value, formatLength);
            
        }
        
        public String getFormat() {
            return format;
        }
        
    }
    
    /**
     * r - 元号の名称と年の場合
     */
    public static class EraNameYearTerm extends DateTerm {
        
        private final String format;
        
        public EraNameYearTerm(final String format) {
            this.format = format;
        } 
        
        @Override
        public String format(final Calendar cal, final MSLocale formatLocale, final Locale runtimeLocale, final boolean isStartDate1904) {
            
            final int formatLength = format.length();
            final Date date = cal.getTime();
            
            final Era era;
            if(formatLocale != null) {
                era = eraResolver.getEra(formatLocale);
            } else {
                era = eraResolver.getEra(runtimeLocale);
            }
            
            if(era.isUnkndown()) {
                // 該当する時代の定義がない場合
                String value = String.valueOf(cal.get(Calendar.YEAR));
                return Utils.supplyZero(value, formatLength);
            }
            
            final EraPeriod period = era.getTargetPeriod(date);
            if(period.isUnknown()) {
                // 期間が不明な場合
                String value = String.valueOf(cal.get(Calendar.YEAR));
                return Utils.supplyZero(value, formatLength);
                
            }
            
            StringBuilder sb = new StringBuilder();
            
            // 元号の組み立て(2桁以上の時に元号を追加)
            if(formatLength >= 2) {
                sb.append(period.getName());
            }
            
            // 年の組み立て
            final String strYear = String.valueOf(period.getEraYear(cal));
            sb.append(Utils.supplyZero(strYear, 2));
            
            return sb.toString();
        }
        
        public String getFormat() {
            return format;
        }
        
    }
    
    /**
     * m - 月の場合
     */
    public static class MonthTerm extends DateTerm {
        
        private final String format;
        
        public MonthTerm(final String format) {
            this.format = format;
        } 
        
        @Override
        public String format(final Calendar cal, final MSLocale formatLocale, final Locale runtimeLocale, final boolean isStartDate1904) {
            
            final int value = cal.get(Calendar.MONTH) + 1;
            final int formatLength = format.length();
            
            if(formatLength == 1) {
                return String.valueOf(value);
                
            } else if(formatLength == 2) {
                return Utils.supplyZero(String.valueOf(value), 2);
                
            } else if(formatLength == 3) {
                // 月名の先頭3文字
                final String key = String.format("month.%d.abbrev", value);
                return DateTerm.messageResolver.getMessage(formatLocale, key);
                
            } else if(formatLength == 4) {
                // 月名
                final String key = String.format("month.%d.name", value);
                return DateTerm.messageResolver.getMessage(formatLocale, key);
                
            } else if(formatLength == 5) {
                // 月名の先頭1文字
                final String key = String.format("month.%d.leading", value);
                return DateTerm.messageResolver.getMessage(formatLocale, key);
                
            } else {
                return Utils.supplyZero(String.valueOf(value), 2);
            }
        }
        
        public String getFormat() {
            return format;
        }
        
    }
    
    /**
     * 曜日のインデックスを取得する。
     * ・日曜始まりで、0から始まる。
     * @param cal
     * @return
     */
    private static int getWeekIndex(final Calendar cal) {
        final int val = cal.get(Calendar.DAY_OF_WEEK);
        switch(val) {
            case Calendar.SUNDAY:
                return 0;
            case Calendar.MONDAY:
                return 1;
            case Calendar.TUESDAY:
                return 2;
            case Calendar.WEDNESDAY:
                return 3;
            case Calendar.THURSDAY:
                return 4;
            case Calendar.FRIDAY:
                return 5;
            case Calendar.SATURDAY:
                return 6;
        }
        
        return 0;
    }
    
    /**
     * d - 日の場合
     * ・dが3~4桁の場合は、英字の曜日。
     */
    public static class DayTerm extends DateTerm {
        
        private final String format;
        
        public DayTerm(final String format) {
            this.format = format;
        } 
        
        @Override
        public String format(final Calendar cal, final MSLocale formatLocale, final Locale runtimeLocale, final boolean isStartDate1904) {
            
            final int value = cal.get(Calendar.DAY_OF_MONTH);
            final int formatLength = format.length();
            
            if(formatLength == 1) {
                return String.valueOf(value);
                
            } else if(formatLength == 2) {
                return Utils.supplyZero(String.valueOf(value), 2); 
                
            } else if(formatLength == 3) {
                // 曜日の省略名
                final int index = getWeekIndex(cal);
                final String key = String.format("week.%d.abbrev", index);
                return messageResolver.getMessage(formatLocale, key);
                
            } else if(formatLength >= 4) {
                // 曜日の正式名
                final int index = getWeekIndex(cal);
                final String key = String.format("week.%d.name", index);
                return messageResolver.getMessage(formatLocale, key);
                
            } else {
               return Utils.supplyZero(String.valueOf(value), 2); 
            }
            
        }
        
        public String getFormat() {
            return format;
        }
        
    }
    
    /**
     * a- 日本語名称の曜日の場合
     * 
     */
    public static class WeekName extends DateTerm {
        
        private final String format;
        
        public WeekName(final String format) {
            this.format = format;
        } 
        
        @Override
        public String format(final Calendar cal, final MSLocale formatLocale, final Locale runtimeLocale, final boolean isStartDate1904) {
            
            final int index = getWeekIndex(cal);
            final int formatLength = format.length();
            
            if(formatLength <= 3) {
                final String key = String.format("week.%d.abbrev", index);
                return messageResolver.getMessage(MSLocale.JAPANESE, key);
            } else {
                final String key = String.format("week.%d.name", index);
                return messageResolver.getMessage(MSLocale.JAPANESE, key);
            }
        }
        
        public String getFormat() {
            return format;
        }
        
    }
    
    /**
     * n- OpenOffice用の日本語名称の曜日の場合
     * 
     */
    public static class WeekNameForOO extends DateTerm {
        
        private final String format;
        
        public WeekNameForOO(final String format) {
            this.format = format;
        } 
        
        @Override
        public String format(final Calendar cal, final MSLocale formatLocale, final Locale runtimeLocale, final boolean isStartDate1904) {
            
            final int index = getWeekIndex(cal);
            final int formatLength = format.length();
            
            if(formatLength <= 2) {
                final String key = String.format("week.%d.abbrev", index);
                return messageResolver.getMessage(MSLocale.JAPANESE, key);
            } else {
                final String key = String.format("week.%d.name", index);
                return messageResolver.getMessage(MSLocale.JAPANESE, key);
            }
        }
        
        public String getFormat() {
            return format;
        }
        
    }
    
    /**
     * ww - 年の週番号を取得する。
     * 
     */
    public static class WeekNumberTerm extends DateTerm {
        
        private final String format;
        
        public WeekNumberTerm(final String format) {
            this.format = format;
        } 
        
        @Override
        public String format(final Calendar cal, final MSLocale formatLocale, final Locale runtimeLocale, final boolean isStartDate1904) {
            
            final int val = cal.get(Calendar.WEEK_OF_YEAR);
            return String.valueOf(val);
           
        }
        
        public String getFormat() {
            return format;
        }
        
    }
    
    /**
     * h - 時間の場合
     */
    public static class HourTerm extends DateTerm {
        
        private final String format;
        
        /**
         * 12時間表示かどうか。
         */
        private final boolean half;
        
        public HourTerm(final String format, final boolean half) {
            this.format = format;
            this.half = half;
        } 
        
        @Override
        public String format(final Calendar cal, final MSLocale formatLocale, final Locale runtimeLocale, final boolean isStartDate1904) {
            
            final String value;
            if(isHalf()) {
                value = String.valueOf(cal.get(Calendar.HOUR));
            } else {
                value = String.valueOf(cal.get(Calendar.HOUR_OF_DAY));
            }
            
            final int formatLength = format.length();
            return Utils.supplyZero(value, formatLength);
            
        }
        
        public boolean isHalf() {
            return half;
        }
        
        public String getFormat() {
            return format;
        }
        
    }
    
    /**
     * m - 分の場合
     */
    public static class MinuteTerm extends DateTerm {
        
        private final String format;
        
        public MinuteTerm(final String format) {
            this.format = format;
        } 
        
        @Override
        public String format(final Calendar cal, final MSLocale formatLocale, final Locale runtimeLocale, final boolean isStartDate1904) {
            
            final String value = String.valueOf(cal.get(Calendar.MINUTE));
            final int formatLength = format.length();
            return Utils.supplyZero(value, formatLength);
            
        }
        
        public String getFormat() {
            return format;
        }
        
    }
    
    /**
     * s - 秒の場合
     */
    public static class SecondTerm extends DateTerm {
        
        private final String format;
        
        public SecondTerm(final String format) {
            this.format = format;
        } 
        
        @Override
        public String format(final Calendar cal, final MSLocale formatLocale, final Locale runtimeLocale, final boolean isStartDate1904) {
            
            final String value = String.valueOf(cal.get(Calendar.SECOND));
            final int formatLength = format.length();
            return Utils.supplyZero(value, formatLength);
            
        }
        
        public String getFormat() {
            return format;
        }
        
    }
    
    /**
     * AM/PM - 午前/午後の場合
     */
    public static class AmPmTerm extends DateTerm {
        
        private final String format;
        
        private final String am;
        
        private final String pm;
        
        public AmPmTerm(final String format) {
            this.format = format;
            
            String[] split = format.split("/");
            if(split.length >= 2) {
                this.am = split[0];
                this.pm = split[1];
            } else {
                this.am = "AM";
                this.pm = "PM";
            }
        } 
        
        @Override
        public String format(final Calendar cal, final MSLocale formatLocale, final Locale runtimeLocale, final boolean isStartDate1904) {
            
            final int val = cal.get(Calendar.AM_PM);
            if(val == Calendar.AM) {
                return messageResolver.getMessage(formatLocale, "day.am.name", am);
                
            } else {
                return messageResolver.getMessage(formatLocale, "day.pm.name", pm);
                
            }
            
        }
        
        public String getFormat() {
            return format;
        }
        
        public String getAm() {
            return am;
        }
        
        public String getPm() {
            return pm;
        }
        
    }
    
    /**
     * q - 四半期の場合
     */
    public static class QuaterTerm extends DateTerm {
        
        private final String format;
        
        public QuaterTerm(final String format) {
            this.format = format;
        } 
        
        @Override
        public String format(final Calendar cal, final MSLocale formatLocale, final Locale runtimeLocale, final boolean isStartDate1904) {
            
            final int index = (cal.get(Calendar.MONTH) / 3) + 1;
            
            // Excelではなく実行環境のロケールによっても変わるため注意
            if(format.length() == 1) {
                final String key = String.format("quaterTerm.%d.abbrev", index);
                if(formatLocale != null) {
                    return messageResolver.getMessage(formatLocale, key);
                } else {
                    return messageResolver.getMessage(runtimeLocale, key);
                    
                }
                
            } else {
                final String key = String.format("quaterTerm.%d.name", index);
                if(formatLocale != null) {
                    return messageResolver.getMessage(formatLocale, key);
                } else {
                    return messageResolver.getMessage(runtimeLocale, key);
                }
            }
            
        }
        
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy