{"id":13613,"date":"2019-09-01T19:49:25","date_gmt":"2019-09-01T17:49:25","guid":{"rendered":"http:\/\/blog.wenzlaff.de\/?p=13613"},"modified":"2021-11-22T17:14:08","modified_gmt":"2021-11-22T16:14:08","slug":"wie-kann-in-java-ein-ical-termin-ics-datei-erzeugt-werden","status":"publish","type":"post","link":"http:\/\/blog.wenzlaff.de\/?p=13613","title":{"rendered":"Wie kann in Java ein ical Termin (ics Datei) erzeugt werden?"},"content":{"rendered":"<p>Wer mit Java <a href=\"https:\/\/de.wikipedia.org\/wiki\/ICalendar\" rel=\"noopener noreferrer\" target=\"_blank\">ical<\/a> Termine erzeugen will, kann das gut mit der <a href=\"https:\/\/github.com\/ical4j\/ical4j\" rel=\"noopener noreferrer\" target=\"_blank\">ical4j<\/a> Lib machen. Es muss dazu in der pom.xml dieser Eintrag hinzugef\u00fcgt werden.<\/p>\n<pre class=\"lang:xhtml decode:true \" >&lt;dependency&gt;\r\n\t&lt;groupId&gt;org.mnode.ical4j&lt;\/groupId&gt;\r\n\t&lt;artifactId&gt;ical4j&lt;\/artifactId&gt;\r\n\t&lt;version&gt;3.0.4&lt;\/version&gt;\r\n&lt;\/dependency&gt;<\/pre>\n<p><a href=\"http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2019\/09\/iCalendar.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2019\/09\/iCalendar.png\" alt=\"\" width=\"2340\" height=\"1586\" class=\"aligncenter size-full wp-image-13617\" srcset=\"http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2019\/09\/iCalendar.png 2340w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2019\/09\/iCalendar-300x203.png 300w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2019\/09\/iCalendar-768x521.png 768w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2019\/09\/iCalendar-1024x694.png 1024w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/a><\/p>\n<p>Dann wollen wir zuerst mal ein paar Zeilen f\u00fcr den JUnit Test daf\u00fcr schreiben:<\/p>\n<pre class=\"lang:java decode:true \" >\r\n\r\n        @Test\r\n\tvoid testWriteKalenderInDatei() throws Exception {\r\n\r\n\t\tCalendar icsCalendar = getTestkalenderMitEinTermin();\r\n\r\n\t\tString icsDateinamen = \"JUnit-Testdatei.ics\";\r\n\t\tKalender.writeKalenderInDatei(icsCalendar, icsDateinamen);\r\n\t}\r\n\r\n\tprivate Calendar getTestkalenderMitEinTermin() {\r\n\t\tCalendar icsCalendar = Kalender.createKalender();\r\n\t\tTimeZone timezone = Kalender.createTimezoneEuropa();\r\n\t\tLocalDateTime eventStartZeitpunkt = LocalDateTime.now();\r\n\t\tString eventKommentar = \"JUnit Test Kommentar\";\r\n\t\tString eventTitel = \"JUnit Event Titel\";\r\n\t\tKalender k = new Kalender();\r\n\t\tk.addTermin(icsCalendar, timezone, eventStartZeitpunkt, eventTitel, eventKommentar);\r\n\t\treturn icsCalendar;\r\n\t}\r\n<\/pre>\n<p>Wir brauchen noch die Kalender Klasse, die hier kopiert werden kann:<!--more--><\/p>\n<pre class=\"lang:java decode:true \" >\r\n\r\nimport java.io.FileOutputStream;\r\nimport java.io.IOException;\r\nimport java.time.LocalDateTime;\r\nimport java.util.GregorianCalendar;\r\n\r\nimport org.apache.logging.log4j.LogManager;\r\nimport org.apache.logging.log4j.Logger;\r\n\r\nimport net.fortuna.ical4j.data.CalendarOutputter;\r\nimport net.fortuna.ical4j.model.Calendar;\r\nimport net.fortuna.ical4j.model.DateTime;\r\nimport net.fortuna.ical4j.model.TimeZone;\r\nimport net.fortuna.ical4j.model.TimeZoneRegistry;\r\nimport net.fortuna.ical4j.model.TimeZoneRegistryFactory;\r\nimport net.fortuna.ical4j.model.component.VEvent;\r\nimport net.fortuna.ical4j.model.component.VTimeZone;\r\nimport net.fortuna.ical4j.model.property.CalScale;\r\nimport net.fortuna.ical4j.model.property.Description;\r\nimport net.fortuna.ical4j.model.property.ProdId;\r\nimport net.fortuna.ical4j.model.property.Uid;\r\nimport net.fortuna.ical4j.model.property.Version;\r\nimport net.fortuna.ical4j.util.RandomUidGenerator;\r\nimport net.fortuna.ical4j.util.UidGenerator;\r\n\r\n\/**\r\n * Ein ics Kalender.\r\n * \r\n * @author Thomas Wenzlaff\r\n *\r\n *\/\r\npublic class Kalender {\r\n\r\n\tprivate static final Logger LOG = LogManager.getLogger(Kalender.class);\r\n\r\n\tprivate static final String PRODUKT_ID = \"-\/\/Thomas Wenzlaff\/\/www.wenzlaff.de 1.0\/\/DE\";\r\n\r\n\tprivate static final int TERMIN_DAUER_IN_MINUTEN = 15;\r\n\r\n\tprivate UidGenerator uidGenerator;\r\n\r\n\t\/**\r\n\t * Konstruktor.\r\n\t *\/\r\n\tpublic Kalender() {\r\n\t\tLOG.debug(\"Konstruktor\");\r\n\t\tuidGenerator = new RandomUidGenerator(); \/\/ wir nutzen den Zufallsgenerator, m\u00f6glich w\u00e4hre auch der FixedUidGenerator\r\n\t}\r\n\r\n\t\/**\r\n\t * F\u00fcgt einen Termin von 15 Minuten Dauer hinzu.\r\n\t * \r\n\t * @param icsCalendar         der Kalender\r\n\t * @param timezone            die Zeitzone\r\n\t * @param eventStartZeitpunkt der Zeitpunkt wo der Termin startet\r\n\t * @param eventTitel          der Titel des Termins\r\n\t * @param eventKommentar      der Kommentar des Termin\r\n\t *\/\r\n\tpublic void addTermin(Calendar icsCalendar, TimeZone timezone, LocalDateTime eventStartZeitpunkt, String eventTitel, String eventKommentar) {\r\n\r\n\t\tjava.util.Calendar startDate = getZeitpunkt(eventStartZeitpunkt, timezone);\r\n\r\n\t\tjava.util.Calendar endDate = getZeitpunkt(eventStartZeitpunkt.plusMinutes(TERMIN_DAUER_IN_MINUTEN), timezone);\r\n\r\n\t\tVEvent bibelleseTermin = erzeugeEvent(startDate, endDate, eventTitel, eventKommentar);\r\n\r\n\t\tVTimeZone tz = timezone.getVTimeZone();\r\n\t\tbibelleseTermin.getProperties().add(tz.getTimeZoneId());\r\n\r\n\t\tsetUid(bibelleseTermin);\r\n\r\n\t\ticsCalendar.getComponents().add(bibelleseTermin);\r\n\t}\r\n\r\n\t\/**\r\n\t * Erzeugt einen Gregorianischen Kalender.\r\n\t * \r\n\t * @return Kalender\r\n\t *\/\r\n\tpublic static Calendar createKalender() {\r\n\r\n\t\tCalendar icsCalendar = new Calendar();\r\n\t\ticsCalendar.getProperties().add(new ProdId(PRODUKT_ID));\r\n\t\ticsCalendar.getProperties().add(Version.VERSION_2_0);\r\n\t\ticsCalendar.getProperties().add(CalScale.GREGORIAN);\r\n\r\n\t\tLOG.info(\"Kalender erzeugt mit ProduktId: \" + icsCalendar.getProductId());\r\n\t\treturn icsCalendar;\r\n\t}\r\n\r\n\t\/**\r\n\t * Erzeugt eine Zeitzone f\u00fcr Europa.\r\n\t * \r\n\t * Wir brauchen das Propertie:\r\n\t * net.fortuna.ical4j.timezone.cache.impl=net.fortuna.ical4j.util.MapTimeZoneCache\r\n\t * in der ical4j.properties\r\n\t * \r\n\t * @return Zeitzone f\u00fcr Europa.\r\n\t *\/\r\n\tpublic static TimeZone createTimezoneEuropa() {\r\n\r\n\t\tTimeZoneRegistry registry = TimeZoneRegistryFactory.getInstance().createRegistry();\r\n\t\tTimeZone timezone = registry.getTimeZone(\"Europe\/Berlin\");\r\n\t\tLOG.info(\"Timezone erzeugt: \" + timezone.getDisplayName());\r\n\t\treturn timezone;\r\n\t}\r\n\r\n\tpublic static void writeKalenderInDatei(Calendar icsCalendar, String icsDateinamen) throws IOException {\r\n\r\n\t\tLOG.debug(\"Schreibe icsCalendar in Datei: \" + icsDateinamen);\r\n\r\n\t\tFileOutputStream fout = new FileOutputStream(icsDateinamen);\r\n\r\n\t\tCalendarOutputter outputter = new CalendarOutputter();\r\n\t\toutputter.output(icsCalendar, fout);\r\n\t}\r\n\r\n\tprivate static VEvent erzeugeEvent(java.util.Calendar startDate, java.util.Calendar endDate, String eventTitel, String eventKommentar) {\r\n\r\n\t\tDateTime start = new DateTime(startDate.getTime());\r\n\t\tDateTime end = new DateTime(endDate.getTime());\r\n\t\tVEvent bibelleseTermin = new VEvent(start, end, eventTitel);\r\n\t\tbibelleseTermin.getProperties().add(new Description(eventKommentar));\r\n\r\n\t\tLOG.debug(\"Erzeugter Start-Event: \" + start + \", Event Titel: \" + eventTitel + \", Kommentar: \" + eventKommentar);\r\n\r\n\t\treturn bibelleseTermin;\r\n\t}\r\n\r\n\tprivate static java.util.Calendar getZeitpunkt(LocalDateTime eventZeitpunkt, TimeZone timezone) {\r\n\r\n\t\tjava.util.Calendar startDate = new GregorianCalendar();\r\n\t\tstartDate.setTimeZone(timezone);\r\n\t\tstartDate.set(java.util.Calendar.MONTH, eventZeitpunkt.getMonthValue() - 1);\r\n\t\tstartDate.set(java.util.Calendar.DAY_OF_MONTH, eventZeitpunkt.getDayOfMonth());\r\n\t\tstartDate.set(java.util.Calendar.YEAR, eventZeitpunkt.getYear());\r\n\t\tstartDate.set(java.util.Calendar.HOUR_OF_DAY, eventZeitpunkt.getHour());\r\n\t\tstartDate.set(java.util.Calendar.MINUTE, eventZeitpunkt.getMinute());\r\n\t\tstartDate.set(java.util.Calendar.SECOND, eventZeitpunkt.getSecond());\r\n\t\treturn startDate;\r\n\t}\r\n\r\n\tprivate void setUid(VEvent termin) {\r\n\r\n\t\tUid uid = uidGenerator.generateUid();\r\n\t\ttermin.getProperties().add(uid);\r\n\t}\r\n\r\n}<\/pre>\n<p>Damit der Test auch durchl\u00e4uft, brauche wir auch noch eine <strong>ical4j.properties<\/strong> Datei mit folgenden Inhalt im <strong>\/src\/man\/resources<\/strong> Verzeichnis, sonst klappt es nicht mit der Zeitzone:<\/p>\n<pre class=\"lang:default decode:true \" >\r\nical4j.unfolding.relaxed=true\r\nical4j.compatibility.outlook=true\r\nical4j.compatibility.notes=true\r\nical4j.parsing.relaxed=true\r\nical4j.validation.relaxed=true\r\nnet.fortuna.ical4j.timezone.cache.impl=net.fortuna.ical4j.util.MapTimeZoneCache<\/pre>\n<p>Wenn der Test erfolgreich durchgelaufen ist:<\/p>\n<p><a href=\"http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2019\/09\/Bildschirmfoto-2019-09-01-um-19.21.08.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2019\/09\/Bildschirmfoto-2019-09-01-um-19.21.08.png\" alt=\"\" width=\"452\" height=\"153\" class=\"aligncenter size-full wp-image-13614\" srcset=\"http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2019\/09\/Bildschirmfoto-2019-09-01-um-19.21.08.png 452w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2019\/09\/Bildschirmfoto-2019-09-01-um-19.21.08-300x102.png 300w\" sizes=\"auto, (max-width: 452px) 100vw, 452px\" \/><\/a><\/p>\n<p>finden wir die isc-Datei mit dem Termin, der in jeden Kalender importiert werden kann:<\/p>\n<pre class=\"lang:default decode:true \" >BEGIN:VCALENDAR\r\nPRODID:-\/\/Thomas Wenzlaff\/\/www.wenzlaff.de 1.0\/\/DE\r\nVERSION:2.0\r\nCALSCALE:GREGORIAN\r\nBEGIN:VEVENT\r\nDTSTAMP:20190901T172105Z\r\nDTSTART:20190901T192104\r\nDTEND:20190901T193604\r\nSUMMARY:JUnit Event Titel\r\nDESCRIPTION:JUnit Test Kommentar\r\nTZID:Europe\/Berlin\r\nUID:4cbf53d2-83e3-488d-b1c5-6e62e2335b56\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Wer mit Java ical Termine erzeugen will, kann das gut mit der ical4j Lib machen. Es muss dazu in der pom.xml dieser Eintrag hinzugef\u00fcgt werden. &lt;dependency&gt; &lt;groupId&gt;org.mnode.ical4j&lt;\/groupId&gt; &lt;artifactId&gt;ical4j&lt;\/artifactId&gt; &lt;version&gt;3.0.4&lt;\/version&gt; &lt;\/dependency&gt; Dann wollen wir zuerst mal ein paar Zeilen f\u00fcr den JUnit Test daf\u00fcr schreiben: @Test void testWriteKalenderInDatei() throws Exception { Calendar icsCalendar = getTestkalenderMitEinTermin(); String &hellip; <\/p>\n<p class=\"link-more\"><a href=\"http:\/\/blog.wenzlaff.de\/?p=13613\" class=\"more-link\"><span class=\"screen-reader-text\">\u201eWie kann in Java ein ical Termin (ics Datei) erzeugt werden?\u201c <\/span>weiterlesen<\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[220,5],"tags":[3753,3751,3752,1511,2178],"class_list":["post-13613","post","type-post","status-publish","format-standard","hentry","category-anleitung","category-java","tag-beispiel-code","tag-ical","tag-ical-kalender","tag-ics","tag-java"],"_links":{"self":[{"href":"http:\/\/blog.wenzlaff.de\/index.php?rest_route=\/wp\/v2\/posts\/13613","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/blog.wenzlaff.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/blog.wenzlaff.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/blog.wenzlaff.de\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/blog.wenzlaff.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=13613"}],"version-history":[{"count":0,"href":"http:\/\/blog.wenzlaff.de\/index.php?rest_route=\/wp\/v2\/posts\/13613\/revisions"}],"wp:attachment":[{"href":"http:\/\/blog.wenzlaff.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=13613"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/blog.wenzlaff.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=13613"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/blog.wenzlaff.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=13613"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}