diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
new file mode 100644
index 0000000..4538e94
--- /dev/null
+++ b/.github/workflows/codeql.yml
@@ -0,0 +1,70 @@
+# For most projects, this workflow file will not need changing; you simply need
+# to commit it to your repository.
+#
+# You may wish to alter this file to override the set of languages analyzed,
+# or to provide custom queries or build logic.
+#
+# ******** NOTE ********
+# We have attempted to detect the languages in your repository. Please check
+# the `language` matrix defined below to confirm you have the correct set of
+# supported CodeQL languages.
+#
+name: "CodeQL"
+
+on:
+ push:
+ branches: [ master ]
+ pull_request:
+ # The branches below must be a subset of the branches above
+ branches: [ master ]
+ schedule:
+ - cron: '20 7 * * 0'
+
+jobs:
+ analyze:
+ name: Analyze
+ runs-on: ubuntu-latest
+ permissions:
+ actions: read
+ contents: read
+ security-events: write
+
+ strategy:
+ fail-fast: false
+ matrix:
+ language: [ 'java' ]
+ # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
+ # Learn more about CodeQL language support at https://git.io/codeql-language-support
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v2
+
+ # Initializes the CodeQL tools for scanning.
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v1
+ with:
+ languages: ${{ matrix.language }}
+ # If you wish to specify custom queries, you can do so here or in a config file.
+ # By default, queries listed here will override any specified in a config file.
+ # Prefix the list here with "+" to use these queries and those in the config file.
+ # queries: ./path/to/local/query, your-org/your-repo/queries@main
+
+ # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
+ # If this step fails, then you should remove it and run the build manually (see below)
+ - name: Autobuild
+ uses: github/codeql-action/autobuild@v1
+
+ # ℹ️ Command-line programs to run using the OS shell.
+ # 📚 https://git.io/JvXDl
+
+ # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
+ # and modify them (or add more) to build your code if your project
+ # uses a compiled language
+
+ #- run: |
+ # make bootstrap
+ # make release
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v1
diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
new file mode 100644
index 0000000..10acad1
--- /dev/null
+++ b/.github/workflows/maven.yml
@@ -0,0 +1,26 @@
+# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
+# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
+
+name: Java CI with Maven
+
+on:
+ push:
+ branches: [ master ]
+ pull_request:
+ branches: [ master ]
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v2
+ - name: Set up JDK 8
+ uses: actions/setup-java@v2
+ with:
+ java-version: '8'
+ distribution: 'adopt'
+ cache: maven
+ - name: Build with Maven
+ run: mvn -B package --file pom.xml
diff --git a/.gitignore b/.gitignore
index 1e74ac4..674e802 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
lib/
tmp/
+local.properties
diff --git a/README.md b/README.md
index bbd76ab..bbfa0cc 100644
--- a/README.md
+++ b/README.md
@@ -4,13 +4,13 @@
Many Utilities
-## 💖 Contents
+## 🧰 Contents
-### 💜 Mime Utility
+### 🔧 Mime Utility
to be deprecated
-### 💜 Ant Tasks
+### 🔧 Ant Tasks
to be deprecated
@@ -19,27 +19,30 @@ to be deprecated
* InOut
* iAppli pak
-### 💜 Java Parser
+### 🔧 Java Parser
to be deprecated
-### 💜 Utility
+### 🔧 Utility
* Japanese Holiday
+ * iCal version
+ * google calendar cloud api version
+ * calculated version
* Password Field
* Singleton
-### 💜 GNU Diff
+### 🔧 GNU Diff
-### 💜 XML
+### 🔧 XML
-### 💜 Ansi Color
+### 🔧 Ansi Color
-### 💜 Grep
+### 🔧 Grep
to be deprecated
-### 💜 Dynamic Morphism
+### 🔧 Dynamic Morphism
### TODO
diff --git a/local.properties.sample b/local.properties.sample
new file mode 100644
index 0000000..e445d24
--- /dev/null
+++ b/local.properties.sample
@@ -0,0 +1 @@
+google.account=you@gmail.com
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 07e885c..5db8c14 100644
--- a/pom.xml
+++ b/pom.xml
@@ -8,35 +8,14 @@
vavi
vavi-commons-sandbox
- 0.4.0
+ 0.4.1
Vavi Commons Sandbox API
https://github.com/umjammer/vavi-commons-sandbox
- 0.4.0
-
- promote instrumentation, engineering io into main stream
-
-0.3.5
-
- maintenance version
-
-0.3.4
-
- change diff package name
- update instrumentation
-
-0.3.3
-
- out source swing related
-
-0.3.2
-
- move LevenshteinDistance to vavi-commons
- add swing xml pretty printer
-
+
TODO
mac finder alias
@@ -48,6 +27,57 @@ TODO
https://github.com/umjammer/vavi-commons-sandbox/issues
+
+
+ local (not on CI)
+
+
+ ${basedir}/local.properties
+
+
+ env.JITPACK
+ !true
+
+
+
+
+
+ org.codehaus.mojo
+ properties-maven-plugin
+ 1.0.0
+
+
+ initialize
+
+ read-project-properties
+
+
+
+ ${basedir}/local.properties
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ ${google.account}
+
+
+ -Djava.util.logging.config.file=${project.build.testOutputDirectory}/logging.properties
+ -Duser.language=ja
+
+ false
+
+
+
+
+
+
+
@@ -90,7 +120,7 @@ TODO
-
+
javacc
javacc
@@ -102,26 +132,15 @@ TODO
-
- org.apache.maven.plugins
- maven-jar-plugin
- 2.3.1
-
-
-
- vavix.util.VaviInstrumentation
- true
- javassist-3.8.0.GA.jar
-
-
-
-
org.apache.maven.plugins
maven-surefire-plugin
- 2.22.2
+ 3.0.0-M5
- -Djava.util.logging.config.file=${project.build.testOutputDirectory}/logging.properties
+
+ -Djava.util.logging.config.file=${project.build.testOutputDirectory}/logging.properties
+ -Duser.language=ja
+
false
@@ -135,11 +154,23 @@ TODO
+
+
+
+ org.junit
+ junit-bom
+ 5.8.1
+ pom
+ import
+
+
+
+
com.github.umjammer
vavi-commons
- 1.1.0
+ 1.1.6
commons-beanutils
@@ -151,6 +182,11 @@ TODO
ant
1.10.11
+
+ com.github.umjammer
+ vavi-util-serdes
+ 1.0.0
+
net.sf.jacob-project
@@ -161,19 +197,29 @@ TODO
org.junit.jupiter
junit-jupiter-api
- 5.3.0
test
org.junit.jupiter
junit-jupiter-engine
- 5.3.0
test
org.junit.platform
junit-platform-commons
- 1.5.2
+ test
+
+
+
+ com.github.umjammer.vavi-net-auth
+ vavi-net-auth-google
+ 0.1.4
+ test
+
+
+ com.google.apis
+ google-api-services-calendar
+ v3-rev409-1.25.0
test
diff --git a/src/main/java/vavi/net/package.html b/src/main/java/vavi/net/package.html
deleted file mode 100644
index 41bd823..0000000
--- a/src/main/java/vavi/net/package.html
+++ /dev/null
@@ -1,57 +0,0 @@
-
-
-
-
-
-
-
-
-
-vavi.net
-
-
-
-
-
-
-ネットワーク関連のクラスを提供します.
-独自のコンテンツハンドラを提供します.
-
-
-java.net.URL
-
-独自プロトコルハンドラの設定方法
-
- java -Djava.protocol.handler.pkgs=package1['|'package2]... MyApp
-
-
-java.net.ContentHandler
-
-独自コンテントハンドラの設定方法
-
- java -Djava.content.handler.pkgs=package1['|'package2]... MyApp
-
-
-java.net.URLConnection#getFileNameMap
-独自ファイル名マップの設定方法
-
- java -Dcontent.types.user.table=property_file MyApp
-
-
-これから実装すること
-
-
-
-
-
-
diff --git a/src/main/java/vavi/net/www/package.html b/src/main/java/vavi/net/www/package.html
deleted file mode 100644
index 19f5144..0000000
--- a/src/main/java/vavi/net/www/package.html
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
-
-
-
-
-
-vavi.net.www.content.image
-
-
-
-
-
-
-WWW で使用するユーティリティクラスを提供します。
-
-
-
-
-
diff --git a/src/main/java/vavi/tools/ant/package.html b/src/main/java/vavi/tools/ant/package.html
deleted file mode 100644
index 63da4c4..0000000
--- a/src/main/java/vavi/tools/ant/package.html
+++ /dev/null
@@ -1,45 +0,0 @@
-
-
-
-
-
-
-
-
-
-vavi.tools.ant
-
-
-
-
-
-
-
-Ant Task 関連のクラスを提供します.
-
-
-これから実装すること
-
-
-
-
-
-
diff --git a/src/main/java/vavi/util/ICal.java b/src/main/java/vavi/util/ICal.java
new file mode 100644
index 0000000..9576a14
--- /dev/null
+++ b/src/main/java/vavi/util/ICal.java
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2022 by Naohide Sano, All rights reserved.
+ *
+ * Programmed by Naohide Sano
+ */
+
+package vavi.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.lang.reflect.ParameterizedType;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Scanner;
+import java.util.logging.Level;
+
+import vavi.beans.BeanUtil;
+import vavi.util.serdes.BeanBinder;
+import vavi.util.serdes.Binder;
+import vavi.util.serdes.Element;
+import vavi.util.serdes.Serdes;
+import vavi.util.serdes.SimpleBeanBinder;
+
+
+/**
+ * ICal.
+ *
+ * @author Naohide Sano (umjammer)
+ * @version 0.00 2022/02/22 umjammer initial version
+ */
+@Serdes(beanBinder = ICal.class)
+public class ICal extends SimpleBeanBinder implements Binder {
+
+ @Serdes
+ public static class VCalendar {
+ @Element("PRODID")
+ String prodId;
+ @Element("VERSION")
+ String vesion;
+ @Element("CALSCALE")
+ String calScale;
+ @Element("METHOD")
+ String method;
+ @Element("X-WR-CALNAME")
+ String xWRCalname;
+ @Element("X-WR-TIMEZONE")
+ String xWRTimeZone;
+ @Element("X-WR-CALDESC")
+ String xWRCaldesc;
+ @Override
+ public String toString() {
+ return prodId + " " + xWRCaldesc + " " + vesion;
+ }
+ }
+
+ @Serdes
+ public static class VEvent implements Comparable {
+ @Element("DTSTART")
+ String dtStart;
+ @Element("DTEND")
+ String dtEndId;
+ @Element("DTSTAMP")
+ String dtStamp;
+ @Element("UID")
+ String uiId;
+ @Element("CLASS")
+ String clazz;
+ @Element("CREATED")
+ String created;
+ @Element("DESCRIPTION")
+ String description;
+ @Element("LAST-MODIFIED")
+ String lastModifiled;
+ @Element("SEQUENCE")
+ String sequence;
+ @Element("STATUS")
+ String status;
+ @Element("SUMMARY")
+ public String summary;
+ @Element("TRANSP")
+ String transp;
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuuMMdd");
+ public LocalDate getDate() {
+ return formatter.parse(dtStart, LocalDate::from);
+ }
+ @Override
+ public String toString() {
+ return getDate() + " " + summary;
+ }
+ @Override
+ public int compareTo(VEvent o) {
+ return this.getDate().compareTo(o.getDate());
+ }
+ }
+
+ @Element
+ public VCalendar calendar;
+
+ @Element
+ public List events;
+
+ /** */
+ static class ICalIOSource implements BeanBinder.IOSource {
+ private Map lines1 = new HashMap<>();
+ private List
* @author Naohide Sano (nsano)
* @version 0.00 050215 nsano initial version
+ * @deprecated use {@link Files#walkFileTree(java.nio.file.Path, java.nio.file.FileVisitor)}
*/
+@Deprecated
@FunctionalInterface
public interface FileDigger {
diff --git a/src/main/java/vavix/util/grep/RegexFileDigger.java b/src/main/java/vavix/util/grep/RegexFileDigger.java
index b8074ea..2c6c2b9 100644
--- a/src/main/java/vavix/util/grep/RegexFileDigger.java
+++ b/src/main/java/vavix/util/grep/RegexFileDigger.java
@@ -9,6 +9,7 @@
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
+import java.nio.file.Files;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -20,7 +21,9 @@
*
* @author Naohide Sano (nsano)
* @version 0.00 050215 nsano initial version
+ * @deprecated use {@link Files#walkFileTree(java.nio.file.Path, java.nio.file.FileVisitor)}
*/
+@Deprecated
public class RegexFileDigger implements FileDigger {
/**
diff --git a/src/main/java/vavix/util/package.html b/src/main/java/vavix/util/package.html
deleted file mode 100644
index 88d7f64..0000000
--- a/src/main/java/vavix/util/package.html
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
-アプリケーションを実装するために便利なクラスを提供します.
-
-
diff --git a/src/test/java/vavi/tools/ant/DiffTaskTest.java b/src/test/java/vavi/tools/ant/DiffTaskTest.java
index 7ba1b3c..70b1231 100644
--- a/src/test/java/vavi/tools/ant/DiffTaskTest.java
+++ b/src/test/java/vavi/tools/ant/DiffTaskTest.java
@@ -6,6 +6,7 @@
package vavi.tools.ant;
+import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
@@ -20,6 +21,7 @@
class DiffTaskTest {
@Test
+ @Disabled
void test() {
fail("Not yet implemented");
}
diff --git a/src/test/java/vavi/util/ICalTest.java b/src/test/java/vavi/util/ICalTest.java
new file mode 100644
index 0000000..d1637ed
--- /dev/null
+++ b/src/test/java/vavi/util/ICalTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2022 by Naohide Sano, All rights reserved.
+ *
+ * Programmed by Naohide Sano
+ */
+
+package vavi.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+
+import org.junit.jupiter.api.Test;
+
+import vavi.util.serdes.Serdes;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+
+/**
+ * ICalTest.
+ *
+ * @author Naohide Sano (umjammer)
+ * @version 0.00 2022/02/22 umjammer initial version
+ */
+class ICalTest {
+
+ @Test
+ void test() throws IOException {
+ InputStream is = ICal.class.getResourceAsStream("/holidays_jp.ics");
+ ICal calendar = new ICal();
+ Serdes.Util.deserialize(is, calendar);
+Debug.println(StringUtil.paramStringDeep(calendar, 2));
+ assertEquals(50, calendar.events.size());
+ }
+
+ @Test
+ void test2() throws IOException {
+ InputStream is = URI.create("https://www.google.com/calendar/ical/japanese%40holiday.calendar.google.com/public/basic.ics").toURL().openStream();
+ ICal calendar = new ICal();
+ Serdes.Util.deserialize(is, calendar);
+calendar.events.stream().sorted().forEach(System.err::println);
+ }
+
+ @Test
+ void test3() throws IOException {
+ InputStream is = URI.create("https://www.google.com/calendar/ical/ja.japanese%23holiday%40group.v.calendar.google.com/public/basic.ics").toURL().openStream();
+ ICal calendar = new ICal();
+ Serdes.Util.deserialize(is, calendar);
+calendar.events.forEach(System.err::println);
+ }
+}
+
+/* */
diff --git a/src/test/java/vavi/util/PasswordFieldTest.java b/src/test/java/vavi/util/PasswordFieldTest.java
index 4cf27c0..b50ec80 100644
--- a/src/test/java/vavi/util/PasswordFieldTest.java
+++ b/src/test/java/vavi/util/PasswordFieldTest.java
@@ -6,12 +6,12 @@
package vavi.util;
-import java.io.IOException;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
-import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
-import static org.junit.jupiter.api.Assertions.fail;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
/**
@@ -20,22 +20,18 @@
* @author Naohide Sano (umjammer)
* @version 0.00 2016/03/09 umjammer initial version
*/
-@Disabled
public class PasswordFieldTest {
@Test
- public void test() {
- fail("Not yet implemented");
+ public void test() throws Exception {
+ InputStream is = new ByteArrayInputStream("p@sswo@d\n".getBytes());
+ char[] password = PasswordField.getPassword(is, "Enter your password:#");
+ assertArrayEquals("p@sswo@d".toCharArray(), password);
}
/** */
- public static void main(String[] argv) {
- char[] password = null;
- try {
- password = PasswordField.getPassword(System.in, "Enter your password:#");
- } catch (IOException ioe) {
- ioe.printStackTrace();
- }
+ public static void main(String[] argv) throws Exception {
+ char[] password = PasswordField.getPassword(System.in, "Enter your password:#");
if (password == null) {
System.out.println("No password entered");
} else {
diff --git a/src/test/java/vavi/util/Singleton2Test.java b/src/test/java/vavi/util/Singleton2Test.java
index 9ebe331..1bd3e76 100644
--- a/src/test/java/vavi/util/Singleton2Test.java
+++ b/src/test/java/vavi/util/Singleton2Test.java
@@ -6,18 +6,20 @@
package vavi.util;
+import org.junit.jupiter.api.Test;
+
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
/**
- * SingletonTest.
+ * Singleton2Test.
*
* @author Naohide Sano (nsano)
* @version 0.00 050914 nsano initial version
*/
@SuppressWarnings("unused")
-public class Singleton2Test {
+class Singleton2Test {
public static class A extends Singleton {
}
@@ -25,8 +27,8 @@ public static class A extends Singleton {
public static class B extends A {
}
- /** */
- public void test1() throws Exception {
+ @Test
+ void test1() throws Exception {
A a = A.getInstance(A.class);
B b = B.getInstance(B.class);
@@ -35,8 +37,8 @@ public void test1() throws Exception {
public static class C extends Singleton {
}
- /** */
- public void test2() throws Exception {
+ @Test
+ void test2() throws Exception {
C c = C.getInstance(C.class);
}
@@ -45,8 +47,8 @@ public D() {
}
}
- /** */
- public void test3() throws Exception {
+ @Test
+ void test3() throws Exception {
D d = D.getInstance(D.class);
}
@@ -54,8 +56,8 @@ public void test3() throws Exception {
public static class E extends Singleton {
}
- /** */
- public void test4() throws Exception {
+ @Test
+ void test4() throws Exception {
E e = E.getInstance(E.class);
assertTrue(true);
try {
@@ -77,8 +79,8 @@ public Object get() {
}
}
- /** */
- public void test5() throws Exception {
+ @Test
+ void test5() throws Exception {
F f = F.getInstance(F.class);
}
}
diff --git a/src/test/java/vavi/util/SingletonTest.java b/src/test/java/vavi/util/SingletonTest.java
index 2d989ee..b2b1816 100644
--- a/src/test/java/vavi/util/SingletonTest.java
+++ b/src/test/java/vavi/util/SingletonTest.java
@@ -7,6 +7,9 @@
package vavi.util;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.fail;
@@ -17,7 +20,7 @@
* @version 0.00 050914 nsano initial version
*/
@SuppressWarnings("unused")
-public class SingletonTest {
+class SingletonTest {
static class A extends Singleton {
}
@@ -25,7 +28,7 @@ static class A extends Singleton {
static class B extends A {
}
- /** */
+ @Test
public void test1() throws Exception {
A a = A.getInstance(A.class);
@@ -37,13 +40,11 @@ private C() {
}
}
- /** */
+ @Test
public void test2() throws Exception {
- try {
+ assertThrows(IllegalStateException.class, () -> {
C c = C.getInstance(C.class);
- fail();
- } catch (IllegalStateException e) {
- }
+ });
}
static class D extends Singleton {
@@ -51,7 +52,7 @@ protected D() {
}
}
- /** */
+ @Test
public void test3() throws Exception {
D d = D.getInstance(D.class);
@@ -60,14 +61,12 @@ public void test3() throws Exception {
static class E extends Singleton {
}
- /** */
+ @Test
public void test4() throws Exception {
- try {
+ assertThrows(IllegalStateException.class, () -> {
E e = E.getInstance(E.class);
e = new E();
- fail();
- } catch (IllegalStateException e) {
- }
+ });
}
interface X {
@@ -82,17 +81,17 @@ public Object get() {
}
}
- /** */
+ @Test
public void test5() throws Exception {
F f = F.getInstance(F.class);
}
- /** */
+ @Test
public void test6() throws Exception {
G g = G.getInstance(G.class);
}
- /** */
+ @Test
public void test7() throws Exception {
H h = H.getInstance(H.class);
}
@@ -114,4 +113,5 @@ public Object get() {
return null;
}
}
+
/* */
diff --git a/src/test/java/vavi/util/holiday/CalculatedHolidaysJaProviderTest.java b/src/test/java/vavi/util/holiday/CalculatedHolidaysJaProviderTest.java
new file mode 100644
index 0000000..cb8f65e
--- /dev/null
+++ b/src/test/java/vavi/util/holiday/CalculatedHolidaysJaProviderTest.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2022 by Naohide Sano, All rights reserved.
+ *
+ * Programmed by Naohide Sano
+ */
+
+package vavi.util.holiday;
+
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+
+import vavi.util.Debug;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+
+
+/**
+ * CalculatedHolidaysJaProviderTest.
+ *
+ * @author Naohide Sano (umjammer)
+ * @version 0.00 2022/02/23 umjammer initial version
+ */
+class CalculatedHolidaysJaProviderTest {
+
+ @Test
+ void test() {
+ CalculatedHolidaysJaProvider provider = new CalculatedHolidaysJaProvider();
+ List holidays = provider.holidays(2022);
+Debug.println("holidays: " + holidays.size());
+ assertNotEquals(0, holidays.size());
+holidays.forEach(System.err::println);
+ assertArrayEquals(HolidaysProviderTest.expected, holidays.stream().map(HolidaysProvider.Holyday::toString).toArray());
+ }
+}
+
+/* */
diff --git a/src/test/java/vavi/util/holiday/GoogleCalendarHolidaysJaProvider.java b/src/test/java/vavi/util/holiday/GoogleCalendarHolidaysJaProvider.java
new file mode 100644
index 0000000..fc9642c
--- /dev/null
+++ b/src/test/java/vavi/util/holiday/GoogleCalendarHolidaysJaProvider.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2022 by Naohide Sano, All rights reserved.
+ *
+ * Programmed by Naohide Sano
+ */
+
+package vavi.util.holiday;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.security.GeneralSecurityException;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.ZoneId;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.stream.Collectors;
+
+import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
+import com.google.api.client.json.gson.GsonFactory;
+import com.google.api.client.util.DateTime;
+import com.google.api.services.calendar.Calendar;
+import com.google.api.services.calendar.model.Events;
+import com.google.auth.http.HttpCredentialsAdapter;
+
+import vavi.net.auth.oauth2.google.GoogleServiceAccountAppCredential;
+import vavi.util.Debug;
+import vavi.util.Locales;
+
+
+/**
+ * GoogleCalendarHolidaysJaProvider.
+ *
+ *
+ * system properties
+ *
+ *
+ * @author Naohide Sano (umjammer)
+ * @version 0.00 2022/02/22 umjammer initial version
+ */
+@Locales(countries = "Japan", languages = "Japanese")
+public class GoogleCalendarHolidaysJaProvider implements HolidaysProvider {
+
+ private static final String calendarId = "japanese__ja@holiday.calendar.google.com";
+
+ private Calendar service;
+
+ {
+ try {
+ GoogleServiceAccountAppCredential appCredential = new GoogleServiceAccountAppCredential("googlecalendar");
+ service = new Calendar.Builder(
+ GoogleNetHttpTransport.newTrustedTransport(),
+ new GsonFactory(),
+ new HttpCredentialsAdapter(appCredential.getRawData()))
+ .setApplicationName(appCredential.getApplicationName())
+ .build();
+ } catch (IOException | GeneralSecurityException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ @Override
+ public List holidays(int year) {
+ try {
+ Events events = service.events().list(calendarId)
+ .setTimeMin(new DateTime(String.format("%04d-01-01T00:00:00.000+09:00", year)))
+ .setTimeMax(new DateTime(String.format("%04d-01-01T00:00:00.000+09:00", year + 1)))
+ .setOrderBy("startTime")
+ .setSingleEvents(true)
+ .execute();
+Debug.println(Level.FINE, "items: " + events.getItems().size());
+//events.getItems().forEach(System.err::println);
+ return events.getItems().stream().map(e -> new Holyday(toLocalDate(e.getStart().getDate()), e.getSummary())).collect(Collectors.toList());
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+
+ private static LocalDate toLocalDate(DateTime dateTime) {
+ return Instant.ofEpochMilli(dateTime.getValue()).atZone(ZoneId.systemDefault()).toLocalDate();
+ }
+}
+
+/* */
diff --git a/src/test/java/vavi/util/holiday/GoogleCalendarTest.java b/src/test/java/vavi/util/holiday/GoogleCalendarTest.java
new file mode 100644
index 0000000..a737761
--- /dev/null
+++ b/src/test/java/vavi/util/holiday/GoogleCalendarTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2022 by Naohide Sano, All rights reserved.
+ *
+ * Programmed by Naohide Sano
+ */
+
+package vavi.util.holiday;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable;
+
+import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
+import com.google.api.client.json.gson.GsonFactory;
+import com.google.api.client.util.DateTime;
+import com.google.api.services.calendar.Calendar;
+import com.google.api.services.calendar.model.CalendarList;
+import com.google.api.services.calendar.model.Event;
+import com.google.api.services.calendar.model.EventDateTime;
+import com.google.auth.http.HttpCredentialsAdapter;
+
+import vavi.net.auth.oauth2.google.GoogleServiceAccountAppCredential;
+import vavi.util.Debug;
+
+
+/**
+ * GoogleCalendarTest.
+ *
+ * @author Naohide Sano (umjammer)
+ * @version 0.00 2022/02/23 umjammer initial version
+ */
+class GoogleCalendarTest {
+
+ // "primary"
+ static final String calendarId = System.getenv("GOOGLE_ACCOUNT");
+
+ @Test
+ @DisabledIfEnvironmentVariable(named = "GITHUB_WORKFLOW", matches = ".*")
+ void test1() throws Exception {
+ GoogleServiceAccountAppCredential appCredential = new GoogleServiceAccountAppCredential("googlecalendar");
+
+ Calendar service = new Calendar.Builder(
+ GoogleNetHttpTransport.newTrustedTransport(),
+ new GsonFactory(),
+ new HttpCredentialsAdapter(appCredential.getRawData()))
+ .setApplicationName(appCredential.getApplicationName())
+ .build();
+
+ CalendarList calendarList = service.calendarList().list().execute();
+calendarList.forEach((k, v) -> {
+ System.err.println(k + ": " + v);
+});
+
+ Event event = new Event()
+ .setSummary("summary")
+ .setDescription("description")
+ .setColorId("2") // green
+ .setStart(new EventDateTime().setDateTime(new DateTime("2022-02-23T08:00:00.000+09:00")))
+ .setEnd(new EventDateTime().setDateTime(new DateTime("2022-02-23T08:00:00.000+09:00")));
+ event = service.events().insert(calendarId, event).execute();
+Debug.println("event: " + event.getId());
+ }
+}
+
+/* */
diff --git a/src/test/java/vavi/util/holiday/HolidaysProviderTest.java b/src/test/java/vavi/util/holiday/HolidaysProviderTest.java
new file mode 100644
index 0000000..c66a451
--- /dev/null
+++ b/src/test/java/vavi/util/holiday/HolidaysProviderTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2022 by Naohide Sano, All rights reserved.
+ *
+ * Programmed by Naohide Sano
+ */
+
+package vavi.util.holiday;
+
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable;
+
+import vavi.util.Debug;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+
+
+/**
+ * HolidaysProviderTest.
+ *
+ * @author Naohide Sano (umjammer)
+ * @version 0.00 2022/02/22 umjammer initial version
+ */
+class HolidaysProviderTest {
+
+ static final String[] expected = {
+ "2022-01-01 元日",
+ "2022-01-10 成人の日",
+ "2022-02-11 建国記念の日",
+ "2022-02-23 天皇誕生日",
+ "2022-03-21 春分の日",
+ "2022-04-29 昭和の日",
+ "2022-05-03 憲法記念日",
+ "2022-05-04 みどりの日",
+ "2022-05-05 こどもの日",
+ "2022-07-18 海の日",
+ "2022-08-11 山の日",
+ "2022-09-19 敬老の日",
+ "2022-09-23 秋分の日",
+ "2022-10-10 スポーツの日",
+ "2022-11-03 文化の日",
+ "2022-11-23 勤労感謝の日",
+ };
+
+ @Test
+ void test() {
+Debug.println("-------- Google Calendar ICal --------");
+ HolidaysProvider provider = new GoogleICalHolidaysJaProvider();
+ List holidays = provider.holidays(2022);
+holidays.stream().sorted().forEach(System.err::println);
+ assertArrayEquals(expected, holidays.stream().map(HolidaysProvider.Holyday::toString).toArray());
+ }
+
+ @Test
+ @DisabledIfEnvironmentVariable(named = "GITHUB_WORKFLOW", matches = ".*")
+ void test2() {
+Debug.println("-------- Google Calendar API --------");
+ HolidaysProvider provider = new GoogleCalendarHolidaysJaProvider();
+ List holidays = provider.holidays(2022);
+holidays.stream().sorted().forEach(System.err::println);
+ assertArrayEquals(expected, holidays.stream().map(HolidaysProvider.Holyday::toString).toArray());
+ }
+}
+
+/* */
diff --git a/src/test/java/vavix/util/BoyerMooreSearchTest.java b/src/test/java/vavix/util/BoyerMooreSearchTest.java
index d531ac0..8723232 100644
--- a/src/test/java/vavix/util/BoyerMooreSearchTest.java
+++ b/src/test/java/vavix/util/BoyerMooreSearchTest.java
@@ -13,13 +13,15 @@
import java.io.InputStream;
import java.util.regex.Pattern;
-import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
import vavi.util.StringUtil;
import vavix.util.grep.FileDigger;
import vavix.util.grep.RegexFileDigger;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
/**
* BoyerMooreSearchTest.
@@ -27,9 +29,18 @@
* @author Naohide Sano (umjammer)
* @version 0.00 2011/02/09 umjammer initial version
*/
-@Disabled
+@SuppressWarnings("deprecation")
public class BoyerMooreSearchTest {
+ @Test
+ void test1() {
+ String a = "sano";
+ String b = "askkkjadkjdsaldsm,sda,ac,./asdklsasanolkasasdj:ask:mkncasdnasnasdnkcasdacsnds";
+ BoyerMooreSearch bm = new BoyerMooreSearch(b.getBytes());
+ int r = bm.indexOf(a.getBytes(), 0);
+ assertEquals(34, r);
+ }
+
/**
* @param args 0: top dir, 1: patern
*/
diff --git a/src/test/java/vavix/util/JapaneseCalendarTest.java b/src/test/java/vavix/util/JapaneseCalendarTest.java
index f088a4c..f4bc9f7 100644
--- a/src/test/java/vavix/util/JapaneseCalendarTest.java
+++ b/src/test/java/vavix/util/JapaneseCalendarTest.java
@@ -9,6 +9,7 @@
import java.util.Calendar;
import java.util.GregorianCalendar;
+import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -20,6 +21,8 @@
* @author Naohide Sano (nsano)
* @version 0.00 050228 nsano initial version
*/
+@Disabled
+@SuppressWarnings("deprecation")
public class JapaneseCalendarTest {
/**
diff --git a/src/test/java/vavix/util/grep/GrepTest.java b/src/test/java/vavix/util/grep/GrepTest.java
index 98334d7..adee94b 100644
--- a/src/test/java/vavix/util/grep/GrepTest.java
+++ b/src/test/java/vavix/util/grep/GrepTest.java
@@ -21,10 +21,11 @@
* @author Naohide Sano (umjammer)
* @version 0.00 2017/11/19 umjammer initial version
*/
-@Disabled
+@SuppressWarnings("deprecation")
public class GrepTest {
@Test
+ @Disabled
public void test() {
fail("Not yet implemented");
}
diff --git a/src/test/resources/holidays_jp.ics b/src/test/resources/holidays_jp.ics
new file mode 100644
index 0000000..d7e1fa8
--- /dev/null
+++ b/src/test/resources/holidays_jp.ics
@@ -0,0 +1,709 @@
+BEGIN:VCALENDAR
+PRODID:-//Google Inc//Google Calendar 70.9054//EN
+VERSION:2.0
+CALSCALE:GREGORIAN
+METHOD:PUBLISH
+X-WR-CALNAME:Holidays in Japan
+X-WR-TIMEZONE:UTC
+X-WR-CALDESC:Holidays and Observances in Japan
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20231009
+DTEND;VALUE=DATE:20231010
+DTSTAMP:20220222T053515Z
+UID:20231009_ft46ok6svkoutsjchbo8absc9c@google.com
+CLASS:PUBLIC
+CREATED:20210826T091534Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091534Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Sports Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20221010
+DTEND;VALUE=DATE:20221011
+DTSTAMP:20220222T053515Z
+UID:20221010_rtcpuhpvop2pgj66lq22fg1568@google.com
+CLASS:PUBLIC
+CREATED:20210826T091534Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091534Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Sports Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20230429
+DTEND;VALUE=DATE:20230430
+DTSTAMP:20220222T053515Z
+UID:20230429_q1j2j800n9dm7hdbqcmnabvqhk@google.com
+CLASS:PUBLIC
+CREATED:20210826T091534Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091534Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Shōwa Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20230101
+DTEND;VALUE=DATE:20230102
+DTSTAMP:20220222T053515Z
+UID:20230101_rrk5srulrhpvc5ifjhj79olvg8@google.com
+CLASS:PUBLIC
+CREATED:20210826T091534Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091534Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:New Year's Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20220101
+DTEND;VALUE=DATE:20220102
+DTSTAMP:20220222T053515Z
+UID:20220101_397kdq4qnp67cipkdr04ct6074@google.com
+CLASS:PUBLIC
+CREATED:20210826T091534Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091534Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:New Year's Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20230211
+DTEND;VALUE=DATE:20230212
+DTSTAMP:20220222T053515Z
+UID:20230211_dvqna68o5kulgcm338vt622fj4@google.com
+CLASS:PUBLIC
+CREATED:20210826T091534Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091534Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:National Foundation Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20210211
+DTEND;VALUE=DATE:20210212
+DTSTAMP:20220222T053515Z
+UID:20210211_uj212dooek2u9g8tkl6nudtgoo@google.com
+CLASS:PUBLIC
+CREATED:20210826T091534Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091534Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:National Foundation Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20231123
+DTEND;VALUE=DATE:20231124
+DTSTAMP:20220222T053515Z
+UID:20231123_h64oemaelu98ophb19q5inievc@google.com
+CLASS:PUBLIC
+CREATED:20210826T091534Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091534Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Labor Thanksgiving Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20210504
+DTEND;VALUE=DATE:20210505
+DTSTAMP:20220222T053515Z
+UID:20210504_hsc8ni6iff03rs4h4h7f1cepqg@google.com
+CLASS:PUBLIC
+CREATED:20210826T091534Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091534Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Greenery Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20210809
+DTEND;VALUE=DATE:20210810
+DTSTAMP:20220222T053515Z
+UID:20210809_jmvh99h5iu40864tqbcm77ju54@google.com
+CLASS:PUBLIC
+CREATED:20210826T091534Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091534Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Day off for Mountain Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20231103
+DTEND;VALUE=DATE:20231104
+DTSTAMP:20220222T053515Z
+UID:20231103_3mh5aq2l6qo6crmqaq640di97c@google.com
+CLASS:PUBLIC
+CREATED:20210826T091534Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091534Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Culture Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20221103
+DTEND;VALUE=DATE:20221104
+DTSTAMP:20220222T053515Z
+UID:20221103_8o8ucgsi2mko02b2msvbc8mqlg@google.com
+CLASS:PUBLIC
+CREATED:20210826T091534Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091534Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Culture Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20230109
+DTEND;VALUE=DATE:20230110
+DTSTAMP:20220222T053515Z
+UID:20230109_bla62qgptg8hu2960q4mmdb6a4@google.com
+CLASS:PUBLIC
+CREATED:20210826T091534Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091534Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Coming of Age Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20220110
+DTEND;VALUE=DATE:20220111
+DTSTAMP:20220222T053515Z
+UID:20220110_ok8kk08li79j9ratuse8uor7g0@google.com
+CLASS:PUBLIC
+CREATED:20210826T091534Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091534Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Coming of Age Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20210505
+DTEND;VALUE=DATE:20210506
+DTSTAMP:20220222T053515Z
+UID:20210505_bbegubh9hfdm7gdejl2iaom348@google.com
+CLASS:PUBLIC
+CREATED:20210826T091534Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091534Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Children's Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20220321
+DTEND;VALUE=DATE:20220322
+DTSTAMP:20220222T053515Z
+UID:20220321_n9cpv0tncp6uqn73u21bfq3ppg@google.com
+CLASS:PUBLIC
+CREATED:20210826T091532Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091532Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Spring Equinox
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20220718
+DTEND;VALUE=DATE:20220719
+DTSTAMP:20220222T053515Z
+UID:20220718_kpubulc3vtp41umq23srmblc2s@google.com
+CLASS:PUBLIC
+CREATED:20210826T091532Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091532Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Sea Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20230102
+DTEND;VALUE=DATE:20230103
+DTSTAMP:20220222T053515Z
+UID:20230102_ai2hjbs8iv1bmqqh71s2t3c91s@google.com
+CLASS:PUBLIC
+CREATED:20210826T091532Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091532Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:New Year's Day observed
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20210101
+DTEND;VALUE=DATE:20210102
+DTSTAMP:20220222T053515Z
+UID:20210101_mleg5uud6ras85ai8j62ug8il8@google.com
+CLASS:PUBLIC
+CREATED:20210826T091532Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091532Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:New Year's Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20211123
+DTEND;VALUE=DATE:20211124
+DTSTAMP:20220222T053515Z
+UID:20211123_ugq00hbkfge8gv5v9tqhp6pia4@google.com
+CLASS:PUBLIC
+CREATED:20210826T091532Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091532Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Labor Thanksgiving Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20230504
+DTEND;VALUE=DATE:20230505
+DTSTAMP:20220222T053515Z
+UID:20230504_cmbj505t90mum8m93p31mhjims@google.com
+CLASS:PUBLIC
+CREATED:20210826T091532Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091532Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Greenery Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20210223
+DTEND;VALUE=DATE:20210224
+DTSTAMP:20220222T053515Z
+UID:20210223_q3h1bgo2b6ui7dl2u4oerrgo50@google.com
+CLASS:PUBLIC
+CREATED:20210826T091532Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091532Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Emperor's Birthday
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20230923
+DTEND;VALUE=DATE:20230924
+DTSTAMP:20220222T053515Z
+UID:20230923_ebsrrjpu3su6viqon1gfvpj5rg@google.com
+CLASS:PUBLIC
+CREATED:20210826T091532Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091532Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Autumn Equinox
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20220923
+DTEND;VALUE=DATE:20220924
+DTSTAMP:20220222T053515Z
+UID:20220923_8i48684dr4ng4nt0pm9bmrp544@google.com
+CLASS:PUBLIC
+CREATED:20210826T091532Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091532Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Autumn Equinox
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20210320
+DTEND;VALUE=DATE:20210321
+DTSTAMP:20220222T053515Z
+UID:20210320_ocp69udn3jkd91d42skgdgkepk@google.com
+CLASS:PUBLIC
+CREATED:20210826T091531Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091531Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Spring Equinox
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20210723
+DTEND;VALUE=DATE:20210724
+DTSTAMP:20220222T053515Z
+UID:20210723_ikluq93b7svr327h36s31abm0g@google.com
+CLASS:PUBLIC
+CREATED:20210826T091531Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091531Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Sports Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20220429
+DTEND;VALUE=DATE:20220430
+DTSTAMP:20220222T053515Z
+UID:20220429_9b54dcof39o3ar3qvfvrqhjp60@google.com
+CLASS:PUBLIC
+CREATED:20210826T091531Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091531Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Shōwa Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20210722
+DTEND;VALUE=DATE:20210723
+DTSTAMP:20220222T053515Z
+UID:20210722_8ej4u248g91m0nk0biquh9udkk@google.com
+CLASS:PUBLIC
+CREATED:20210826T091531Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091531Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Sea Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20230918
+DTEND;VALUE=DATE:20230919
+DTSTAMP:20220222T053515Z
+UID:20230918_oadebhtv0gpvj426ofq5i8rd4s@google.com
+CLASS:PUBLIC
+CREATED:20210826T091531Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091531Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Respect for the Aged Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20220919
+DTEND;VALUE=DATE:20220920
+DTSTAMP:20220222T053515Z
+UID:20220919_rfak35qnr41nfhrno9c20ftd0g@google.com
+CLASS:PUBLIC
+CREATED:20210826T091531Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091531Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Respect for the Aged Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20220211
+DTEND;VALUE=DATE:20220212
+DTSTAMP:20220222T053515Z
+UID:20220211_rtdnuukd8lta4ri0p5p5beonh8@google.com
+CLASS:PUBLIC
+CREATED:20210826T091531Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091531Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:National Foundation Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20230811
+DTEND;VALUE=DATE:20230812
+DTSTAMP:20220222T053515Z
+UID:20230811_efhua2tidv57dbm39j6envoovs@google.com
+CLASS:PUBLIC
+CREATED:20210826T091531Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091531Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Mountain Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20220811
+DTEND;VALUE=DATE:20220812
+DTSTAMP:20220222T053515Z
+UID:20220811_hgqb6e03l4980njjesl8po4g58@google.com
+CLASS:PUBLIC
+CREATED:20210826T091531Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091531Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Mountain Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20220504
+DTEND;VALUE=DATE:20220505
+DTSTAMP:20220222T053515Z
+UID:20220504_eincm31lk74dvs5ai3qdk741es@google.com
+CLASS:PUBLIC
+CREATED:20210826T091531Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091531Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Greenery Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20230223
+DTEND;VALUE=DATE:20230224
+DTSTAMP:20220222T053515Z
+UID:20230223_g9slgj8989tlggqief38gfjjhs@google.com
+CLASS:PUBLIC
+CREATED:20210826T091531Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091531Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Emperor's Birthday
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20220223
+DTEND;VALUE=DATE:20220224
+DTSTAMP:20220222T053515Z
+UID:20220223_e23m6pvk3dnhck0p2qvp75ek70@google.com
+CLASS:PUBLIC
+CREATED:20210826T091531Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091531Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Emperor's Birthday
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20230503
+DTEND;VALUE=DATE:20230504
+DTSTAMP:20220222T053515Z
+UID:20230503_j90fqhprqvasmkfcm0pjr05078@google.com
+CLASS:PUBLIC
+CREATED:20210826T091531Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091531Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Constitution Memorial Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20220503
+DTEND;VALUE=DATE:20220504
+DTSTAMP:20220222T053515Z
+UID:20220503_fc8o5rd1cs29qte0dr5qd3uitc@google.com
+CLASS:PUBLIC
+CREATED:20210826T091531Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091531Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Constitution Memorial Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20230505
+DTEND;VALUE=DATE:20230506
+DTSTAMP:20220222T053515Z
+UID:20230505_0aht8s6qqjft4opu9dioml8jmk@google.com
+CLASS:PUBLIC
+CREATED:20210826T091531Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091531Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Children's Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20220505
+DTEND;VALUE=DATE:20220506
+DTSTAMP:20220222T053515Z
+UID:20220505_thlmv8udatnq9u0dtf03eh84s8@google.com
+CLASS:PUBLIC
+CREATED:20210826T091531Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091531Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Children's Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20230321
+DTEND;VALUE=DATE:20230322
+DTSTAMP:20220222T053515Z
+UID:20230321_dnnbq8ih3vvqi0rs2ccrgrkdos@google.com
+CLASS:PUBLIC
+CREATED:20210826T091529Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091529Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Spring Equinox
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20210429
+DTEND;VALUE=DATE:20210430
+DTSTAMP:20220222T053515Z
+UID:20210429_tdgv2cl0b55ctlcd3p3cf8rh68@google.com
+CLASS:PUBLIC
+CREATED:20210826T091529Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091529Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Shōwa Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20230717
+DTEND;VALUE=DATE:20230718
+DTSTAMP:20220222T053515Z
+UID:20230717_3hf06eg8bus6qde1mma9lefhf8@google.com
+CLASS:PUBLIC
+CREATED:20210826T091529Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091529Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Sea Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20210920
+DTEND;VALUE=DATE:20210921
+DTSTAMP:20220222T053515Z
+UID:20210920_a4ku0ni5410r695ape8n2tba2o@google.com
+CLASS:PUBLIC
+CREATED:20210826T091529Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091529Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Respect for the Aged Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20210808
+DTEND;VALUE=DATE:20210809
+DTSTAMP:20220222T053515Z
+UID:20210808_jmu38tp6n1b0v5u5iehf4lq924@google.com
+CLASS:PUBLIC
+CREATED:20210826T091529Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091529Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Mountain Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20221123
+DTEND;VALUE=DATE:20221124
+DTSTAMP:20220222T053515Z
+UID:20221123_vuun12ojbcic5bnocijrb2s88k@google.com
+CLASS:PUBLIC
+CREATED:20210826T091529Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091529Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Labor Thanksgiving Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20211103
+DTEND;VALUE=DATE:20211104
+DTSTAMP:20220222T053515Z
+UID:20211103_2rjfbd04vrhr03hfrdc7t8if30@google.com
+CLASS:PUBLIC
+CREATED:20210826T091529Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091529Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Culture Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20210503
+DTEND;VALUE=DATE:20210504
+DTSTAMP:20220222T053515Z
+UID:20210503_7jhqsv3opo75q8oq4r1ud3dkh4@google.com
+CLASS:PUBLIC
+CREATED:20210826T091529Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091529Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Constitution Memorial Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20210111
+DTEND;VALUE=DATE:20210112
+DTSTAMP:20220222T053515Z
+UID:20210111_2vvdoj7kdvl71qudvqfp19ps3k@google.com
+CLASS:PUBLIC
+CREATED:20210826T091529Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091529Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Coming of Age Day
+TRANSP:TRANSPARENT
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20210923
+DTEND;VALUE=DATE:20210924
+DTSTAMP:20220222T053515Z
+UID:20210923_cif5a7mtkrmeqohc7ostrqaekk@google.com
+CLASS:PUBLIC
+CREATED:20210826T091529Z
+DESCRIPTION:Public holiday
+LAST-MODIFIED:20210826T091529Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:Autumn Equinox
+TRANSP:TRANSPARENT
+END:VEVENT
+END:VCALENDAR
diff --git a/src/test/resources/logging.properties b/src/test/resources/logging.properties
new file mode 100644
index 0000000..7d4759c
--- /dev/null
+++ b/src/test/resources/logging.properties
@@ -0,0 +1,8 @@
+handlers=java.util.logging.ConsoleHandler
+.level=INFO
+# Limit the message that are printed on the console to INFO and above.
+java.util.logging.ConsoleHandler.level=INFO
+java.util.logging.ConsoleHandler.formatter=vavi.util.logging.VaviFormatter
+#java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
+# %1:date/time %2:className and methodName %3logName %4:level %5:message %6:errormessage
+java.util.logging.SimpleFormatter.format=%1$tY/%1$tm/%1$td %1$tH:%1$tM:%1$tS.%1$tL [%4$s] %5$s %6$s