Last active
August 4, 2026 05:46
-
-
Save asdf913/f3c1dd49562542a0d25a9f263420098f to your computer and use it in GitHub Desktop.
JapaneseDateWesternDateSpreadSheet (Java 24)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import java.io.File; | |
| import java.io.FileOutputStream; | |
| import java.io.IOException; | |
| import java.io.InputStream; | |
| import java.io.OutputStream; | |
| import java.lang.classfile.ClassFile; | |
| import java.lang.classfile.ClassFileElement; | |
| import java.lang.classfile.ClassModel; | |
| import java.lang.classfile.CodeElement; | |
| import java.lang.classfile.CodeModel; | |
| import java.lang.classfile.CompoundElement; | |
| import java.lang.classfile.MethodModel; | |
| import java.lang.classfile.constantpool.ClassEntry; | |
| import java.lang.classfile.constantpool.Utf8Entry; | |
| import java.lang.classfile.instruction.ConstantInstruction.ArgumentConstantInstruction; | |
| import java.lang.classfile.instruction.ConstantInstruction.IntrinsicConstantInstruction; | |
| import java.lang.classfile.instruction.InvokeInstruction; | |
| import java.lang.constant.ConstantDesc; | |
| import java.lang.reflect.Constructor; | |
| import java.lang.reflect.InvocationTargetException; | |
| import java.text.DateFormat; | |
| import java.text.SimpleDateFormat; | |
| import java.time.chrono.JapaneseEra; | |
| import java.util.ArrayList; | |
| import java.util.Arrays; | |
| import java.util.Calendar; | |
| import java.util.Collection; | |
| import java.util.Collections; | |
| import java.util.Date; | |
| import java.util.List; | |
| import java.util.Locale; | |
| import java.util.Objects; | |
| import java.util.Optional; | |
| import java.util.function.Consumer; | |
| import java.util.function.Function; | |
| import java.util.function.ObjIntConsumer; | |
| import java.util.function.Predicate; | |
| import java.util.function.ToIntFunction; | |
| import java.util.stream.Stream; | |
| import org.apache.commons.collections4.IterableUtils; | |
| import org.apache.commons.lang3.ObjectUtils; | |
| import org.apache.commons.lang3.StringUtils; | |
| import org.apache.commons.lang3.function.TriConsumer; | |
| import org.apache.poi.ss.usermodel.AutoFilter; | |
| import org.apache.poi.ss.usermodel.Cell; | |
| import org.apache.poi.ss.usermodel.Row; | |
| import org.apache.poi.ss.usermodel.Sheet; | |
| import org.apache.poi.ss.usermodel.Workbook; | |
| import org.apache.poi.ss.util.CellRangeAddress; | |
| import org.apache.poi.xssf.usermodel.XSSFWorkbook; | |
| public class JapaneseDateWesternDateSpreadSheet24 { | |
| private static class YearMonthDay { | |
| private int year, month, day; | |
| @Override | |
| public String toString() { | |
| // | |
| final StringBuilder sb = new StringBuilder(StringUtils.leftPad(Integer.toString(year), 4, '0')); | |
| // | |
| sb.append(StringUtils.leftPad(Integer.toString(month), 2, '0')); | |
| // | |
| return Objects.toString(sb.append(StringUtils.leftPad(Integer.toString(day), 2, '0'))); | |
| // | |
| } | |
| } | |
| public static void main(final String[] args) | |
| throws IOException, IllegalAccessException, InstantiationException, InvocationTargetException { | |
| // | |
| // https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/time/chrono/JapaneseEra.java | |
| // | |
| // {Meiji=1868-01-01, Taisho=1912-07-30, Showa=1926-12-25, Heisei=1989-01-08, | |
| // Reiwa=2019-05-01} | |
| // | |
| // Year Month Day 年号 | |
| // 1868 1 1 明治 元 明治元年 | |
| // | |
| final List<YearMonthDay> japaneseEraSinceDates = getJapaneseEraSinceDates(); | |
| // | |
| final YearMonthDay firstJapaneseEraSinceDate = Collections.min(japaneseEraSinceDates, | |
| (a, b) -> compare(Objects.toString(a), Objects.toString(b), -1)); | |
| // | |
| Calendar calendar = null; | |
| // | |
| if (firstJapaneseEraSinceDate != null && (calendar = Calendar.getInstance()) != null) { | |
| // | |
| calendar.set(firstJapaneseEraSinceDate.year, firstJapaneseEraSinceDate.month - 1, | |
| firstJapaneseEraSinceDate.day, 0, 0, 0); | |
| // | |
| calendar.set(Calendar.MILLISECOND, 0); | |
| // | |
| } // if | |
| // | |
| final Calendar now = Calendar.getInstance(); | |
| // | |
| List<Date> dates = null; | |
| // | |
| while (calendar != null && ObjectUtils.compare(calendar, now) <= 0) { | |
| // | |
| add(dates = ObjectUtils.getIfNull(dates, ArrayList::new), getTime(calendar)); | |
| // | |
| calendar.add(Calendar.DATE, 1); | |
| // | |
| } // while | |
| // | |
| final File file = new File("JapaneseDateWesternDateSpreadSheet.xlsx"); | |
| // | |
| try (final Workbook wb = new XSSFWorkbook(); final OutputStream os = new FileOutputStream(file)) { | |
| // | |
| Date date = null; | |
| // | |
| Sheet sheet = null; | |
| // | |
| int physicalNumberOfRows; | |
| // | |
| Row row; | |
| // | |
| Constructor<?> constructor = null; | |
| // | |
| Locale locale = null; | |
| // | |
| TriConsumer<Cell, Calendar, DateFormat> triConsumer = null; | |
| // | |
| Function<Row, Cell> function = null; | |
| // | |
| for (int i = 0; i < IterableUtils.size(dates); i++) { | |
| // | |
| if ((date = IterableUtils.get(dates, i)) == null) { | |
| // | |
| continue; | |
| // | |
| } // if | |
| // | |
| if ((sheet = ObjectUtils.getIfNull(sheet, () -> wb.createSheet())) == null) { | |
| // | |
| continue; | |
| // | |
| } // if | |
| // | |
| if ((physicalNumberOfRows = sheet.getPhysicalNumberOfRows()) == 0 | |
| && (row = sheet.createRow(physicalNumberOfRows)) != null) { | |
| // | |
| setCellValue(row.createCell(row.getPhysicalNumberOfCells()), "Year"); | |
| // | |
| setCellValue(row.createCell(row.getPhysicalNumberOfCells()), "Month"); | |
| // | |
| setCellValue(row.createCell(row.getPhysicalNumberOfCells()), "Day"); | |
| // | |
| setCellValue(row.createCell(row.getPhysicalNumberOfCells()), "年号"); | |
| // | |
| setBlank(row.createCell(row.getPhysicalNumberOfCells())); | |
| // | |
| setBlank(row.createCell(row.getPhysicalNumberOfCells())); | |
| // | |
| } // if | |
| // | |
| if ((row = sheet.createRow(sheet.getPhysicalNumberOfRows())) == null) { | |
| // | |
| continue; | |
| // | |
| } // if | |
| // | |
| setTime(calendar = Calendar.getInstance(), date); | |
| // | |
| testAndAccept(Objects::nonNull, | |
| apply(function = ObjectUtils.getIfNull(function, | |
| () -> (x) -> x != null ? x.createCell(x.getPhysicalNumberOfCells()) : null), row), | |
| calendar, JapaneseDateWesternDateSpreadSheet24::setCellValue, a -> get(a, Calendar.YEAR, 0), 0, | |
| JapaneseDateWesternDateSpreadSheet24::setBlank); | |
| // | |
| testAndAccept(Objects::nonNull, apply(function, row), calendar, | |
| JapaneseDateWesternDateSpreadSheet24::setCellValue, a -> get(a, Calendar.MONTH, 0) + 1, 1, | |
| JapaneseDateWesternDateSpreadSheet24::setBlank); | |
| // | |
| testAndAccept(Objects::nonNull, apply(function, row), calendar, | |
| JapaneseDateWesternDateSpreadSheet24::setCellValue, a -> get(a, Calendar.DATE, 0), 0, | |
| JapaneseDateWesternDateSpreadSheet24::setBlank); | |
| // | |
| if (constructor == null) { | |
| // | |
| final List<Constructor<?>> list = toList( | |
| filter(testAndApply(Objects::nonNull, Locale.class.getConstructors(), Arrays::stream, null), | |
| c -> c != null && Arrays.equals(c.getParameterTypes(), | |
| new Class<?>[] { String.class, String.class, String.class }))); | |
| // | |
| if (IterableUtils.size(list) > 1) { | |
| // | |
| throw new IllegalStateException(); | |
| // | |
| } else if (IterableUtils.size(list) == 1) { | |
| // | |
| constructor = IterableUtils.get(list, 0); | |
| // | |
| } // if | |
| // | |
| } // if | |
| // | |
| if (locale == null) { | |
| // | |
| locale = cast(Locale.class, newInstance(constructor, "ja", "JP", "JP")); | |
| // | |
| } // if | |
| // | |
| testAndAccept(Objects::nonNull, apply(function, row), calendar, new SimpleDateFormat("G", locale), | |
| triConsumer = ObjectUtils.getIfNull(triConsumer, | |
| () -> (a, b, c) -> setCellValue(a, format(c, getTime(b)))), | |
| JapaneseDateWesternDateSpreadSheet24::setBlank); | |
| // | |
| testAndAccept(Objects::nonNull, apply(function, row), calendar, new SimpleDateFormat("yyyy", locale), | |
| triConsumer, JapaneseDateWesternDateSpreadSheet24::setBlank); | |
| // | |
| testAndAccept(Objects::nonNull, apply(function, row), calendar, new SimpleDateFormat("Gyyyy年", locale), | |
| triConsumer, JapaneseDateWesternDateSpreadSheet24::setBlank); | |
| // | |
| } // for | |
| // | |
| setAutoFilter(sheet, new CellRangeAddress(0, sheet.getLastRowNum(), 0, 5)); | |
| // | |
| wb.write(os); | |
| // | |
| } // try | |
| // | |
| System.out.println(file.getAbsolutePath()); | |
| // | |
| } | |
| private static AutoFilter setAutoFilter(final Sheet instance, final CellRangeAddress range) { | |
| return instance != null ? instance.setAutoFilter(range) : null; | |
| } | |
| private static String format(final DateFormat instance, final Date date) { | |
| return instance != null ? instance.format(date) : null; | |
| } | |
| private static <T, U, R> void testAndAccept(final Predicate<U> predicate, final T t, final U u, | |
| final ObjIntConsumer<T> consumerTrue, final ToIntFunction<U> toIntFunction, final int defaultValue, | |
| final Consumer<T> consumerFalse) { | |
| // | |
| if (test(predicate, u)) { | |
| // | |
| accept(consumerTrue, t, toIntFunction != null ? toIntFunction.applyAsInt(u) : defaultValue); | |
| // | |
| } else { | |
| // | |
| accept(consumerFalse, t); | |
| // | |
| } // if | |
| // | |
| } | |
| private static <T, U> void accept(final ObjIntConsumer<T> instance, final T t, final int u) { | |
| if (instance != null) { | |
| instance.accept(t, u); | |
| } | |
| } | |
| private static <T, U, R> void testAndAccept(final Predicate<U> predicate, final T t, final U u, final R r, | |
| final TriConsumer<T, U, R> consumerTrue, final Consumer<T> consumerFalse) { | |
| // | |
| if (test(predicate, u)) { | |
| // | |
| accept(consumerTrue, t, u, r); | |
| // | |
| } else { | |
| // | |
| accept(consumerFalse, t); | |
| // | |
| } // if | |
| // | |
| } | |
| private static <T> void accept(final Consumer<T> instance, final T value) { | |
| if (instance != null) { | |
| instance.accept(value); | |
| } | |
| } | |
| private static <T, U, R> void accept(final TriConsumer<T, U, R> instance, final T t, final U u, final R r) { | |
| if (instance != null) { | |
| instance.accept(t, u, r); | |
| } | |
| } | |
| private static int get(final Calendar instance, final int field, final int defaultValue) { | |
| return instance != null ? instance.get(field) : defaultValue; | |
| } | |
| private static Date getTime(final Calendar instance) { | |
| return instance != null ? instance.getTime() : null; | |
| } | |
| private static void setTime(final Calendar instance, final Date time) { | |
| if (instance != null) { | |
| instance.setTime(time); | |
| } | |
| } | |
| private static void setBlank(final Cell instance) { | |
| if (instance != null) { | |
| instance.setBlank(); | |
| } | |
| } | |
| private static void setCellValue(final Cell instance, final double value) { | |
| if (instance != null) { | |
| instance.setCellValue(value); | |
| } | |
| } | |
| private static void setCellValue(final Cell instance, final String value) { | |
| if (instance != null) { | |
| instance.setCellValue(value); | |
| } | |
| } | |
| private static <T> T newInstance(final Constructor<T> instance, final Object... args) | |
| throws InstantiationException, IllegalAccessException, InvocationTargetException { | |
| return instance != null ? instance.newInstance(args) : null; | |
| } | |
| private static int compare(final String a, final String b, final int defaultValue) { | |
| return a != null ? a.compareTo(b) : defaultValue; | |
| } | |
| private static List<YearMonthDay> getJapaneseEraSinceDates() throws IOException { | |
| // | |
| List<YearMonthDay> list = null; | |
| // | |
| final Class<?> clz = JapaneseEra.class; | |
| // | |
| try (final InputStream is = getResourceAsStream(clz, | |
| StringUtils.join("/", replace(getName(clz), ".", "/"), ".class"))) { | |
| // | |
| final List<MethodModel> mms = toList(filter(stream(methods(parse(ClassFile.of(), readAllBytes(is)))), | |
| m -> Objects.equals(stringValue(methodName(m)), "<clinit>"))); | |
| // | |
| MethodModel mm = null; | |
| // | |
| if (IterableUtils.size(mms) > 1) { | |
| // | |
| throw new IllegalStateException(); | |
| // | |
| } else if (IterableUtils.size(mms) == 1) { | |
| // | |
| mm = IterableUtils.get(mms, 0); | |
| // | |
| } // if | |
| // | |
| final List<CodeElement> ces = elementList(testAndApply(JapaneseDateWesternDateSpreadSheet24::isPresent, | |
| code(mm), JapaneseDateWesternDateSpreadSheet24::get, null)); | |
| // | |
| CodeElement ce = null; | |
| // | |
| Number year = null, month = null, day = null; | |
| // | |
| YearMonthDay yearMonthDay = null; | |
| // | |
| for (int i = 0; i < IterableUtils.size(ces); i++) { | |
| // | |
| if ((ce = IterableUtils.get(ces, i)) == null) { | |
| // | |
| continue; | |
| // | |
| } // if | |
| // | |
| year = month = day = null; | |
| // | |
| if (ce instanceof InvokeInstruction ii && ii != null | |
| && Objects.equals(stringValue(name(ii.owner())), "java/time/LocalDate")) { | |
| // | |
| if (i > 2) { | |
| // | |
| year = getNumber(IterableUtils.get(ces, i - 3)); | |
| // | |
| month = getNumber(IterableUtils.get(ces, i - 2)); | |
| // | |
| day = getNumber(IterableUtils.get(ces, i - 1)); | |
| // | |
| } // if | |
| // | |
| if ((yearMonthDay = year != null && month != null && day != null ? new YearMonthDay() | |
| : null) != null) { | |
| // | |
| yearMonthDay.year = year.intValue(); | |
| // | |
| yearMonthDay.month = month.intValue(); | |
| // | |
| yearMonthDay.day = day.intValue(); | |
| // | |
| add(list = ObjectUtils.getIfNull(list, ArrayList::new), yearMonthDay); | |
| // | |
| } // if | |
| // | |
| } // if | |
| // | |
| } // for | |
| // | |
| } // try | |
| // | |
| return list; | |
| // | |
| } | |
| private static Utf8Entry name(final ClassEntry instance) { | |
| return instance != null ? instance.name() : null; | |
| } | |
| private static String stringValue(final Utf8Entry instance) { | |
| return instance != null ? instance.stringValue() : null; | |
| } | |
| private static Utf8Entry methodName(final MethodModel instance) { | |
| return instance != null ? instance.methodName() : null; | |
| } | |
| private static String getName(final Class<?> instance) { | |
| return instance != null ? instance.getName() : null; | |
| } | |
| private static InputStream getResourceAsStream(final Class<?> instance, final String path) { | |
| return instance != null ? instance.getResourceAsStream(path) : null; | |
| } | |
| private static byte[] readAllBytes(final InputStream instance) throws IOException { | |
| return instance != null ? instance.readAllBytes() : null; | |
| } | |
| private static List<MethodModel> methods(final ClassModel instance) { | |
| return instance != null ? instance.methods() : null; | |
| } | |
| private static ClassModel parse(final ClassFile instance, final byte[] bytes) { | |
| return instance != null ? instance.parse(bytes) : null; | |
| } | |
| private static <E> Stream<E> stream(final Collection<E> instance) { | |
| return instance != null ? instance.stream() : null; | |
| } | |
| private static <E> void add(final Collection<E> instance, final E item) { | |
| if (instance != null) { | |
| instance.add(item); | |
| } | |
| } | |
| private static Number getNumber(final CodeElement instance) { | |
| // | |
| if (instance instanceof ArgumentConstantInstruction aci && aci != null) { | |
| // | |
| return aci.constantValue(); | |
| // | |
| } else if (instance instanceof IntrinsicConstantInstruction ici && ici != null) { | |
| // | |
| final ConstantDesc cv = ici.constantValue(); | |
| // | |
| return cv instanceof Number ? cast(Number.class, cv) : null; | |
| // | |
| } // if | |
| // | |
| return null; | |
| // | |
| } | |
| private static <E extends ClassFileElement> List<E> elementList(final CompoundElement<E> instance) { | |
| return instance != null ? instance.elementList() : null; | |
| } | |
| private static <T> T get(final Optional<T> instnace) { | |
| return instnace != null && instnace.isPresent() ? instnace.get() : null; | |
| } | |
| private static boolean isPresent(final Optional<?> instnace) { | |
| return instnace != null && instnace.isPresent(); | |
| } | |
| private static Optional<CodeModel> code(final MethodModel instance) { | |
| return instance != null ? instance.code() : null; | |
| } | |
| private static <T, R> R testAndApply(final Predicate<T> predicate, final T value, final Function<T, R> functionTrue, | |
| final Function<T, R> functionFalse) { | |
| return test(predicate, value) ? apply(functionTrue, value) : apply(functionFalse, value); | |
| } | |
| private static <T> boolean test(final Predicate<T> instance, final T value) { | |
| return instance != null && instance.test(value); | |
| } | |
| private static <T, R> R apply(final Function<T, R> instance, final T value) { | |
| return instance != null ? instance.apply(value) : null; | |
| } | |
| private static <T> List<T> toList(final Stream<T> instance) { | |
| return instance != null ? instance.toList() : null; | |
| } | |
| private static <T> Stream<T> filter(final Stream<T> instance, final Predicate<? super T> predicate) { | |
| return instance != null ? instance.filter(predicate) : instance; | |
| } | |
| private static String replace(final String instance, final CharSequence target, final CharSequence replacement) { | |
| return instance != null ? instance.replace(target, replacement) : null; | |
| } | |
| private static <T> T cast(final Class<T> clz, final Object instance) { | |
| return clz != null && clz.isInstance(instance) ? clz.cast(instance) : null; | |
| } | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/lang/classfile/package-summary.html