Advanced date, time and interval library for Java with sun/moon-astronomy and calendars like Chinese, Coptic, Ethiopian, French Republican, Hebrew, Hijri, Historic Christian, Indian National, Japanese, Julian, Korean, Minguo, Persian, Thai, Vietnamese



Advanced date, time and interval library for Java


Time4J is thought as a complete and high-end replacement for old java classes around java.util.Date, java.util.Calendar and java.text.SimpleDateFormat. This project is also intended as first-class alternative to the popular libraries JodaTime and its successor JSR-310 (Threeten) since the target audience of Time4J will not only be business Java developers, but also developers with a more scientific background (for example extended time scale support including leap seconds or historically accurate dates).

Although the new JSR-310 (built in Java 8) is certainly a very useful library for many business developers it also has some severe and intentional limitations. Time4J intends to fill all gaps in the future so justifying its co-existence. The interoperability with java.time-package is supported by easily available conversion methods.

Current state and introduction:

On 2020-09-13, the version v5.7 of Time4J has been finished and released. It requires at least Java-8. The older version lines v3.x and v4.x have reached end-of-life with the latest versions v3.50 and v4.38 where v3.x is based on Java 6+7. The previous version lines v1.x and v2.x are no longer recommended (due to several backward incompatibilities) and have reached end-of-life, too. Time4J is organized in modules. The module time4j-base is always necessary. Other modules are optional and include:

  • time4j-sqlxml contains a simple adapter for the support of SQL-databases.
  • time4j-tzdata encapsulates the time zone repository (independent github-project starting with version 5.0-2018f)
  • time4j-ui with JavaFX-features (includes a calendar picker)

For Android support please refer to the sister project Time4A.

Standard use cases will be covered by the main package "net.time4j". It offers four basic temporal types.

  • PlainDate = calendar date strictly following ISO-8601
  • PlainTime = wall time (on an analogous clock) including 24:00-support and flexible dayperiods
  • PlainTimestamp = local timestamp as composition of calendar date and wall time
  • Moment = global timestamp which refers to true UTC standard including leapsecond-support

Here some examples as a flavour of how Time4J-code looks like (shown code valid for v5.0 or later):

import net.time4j.*;
import net.time4j.format.TextWidth;

import java.util.Locale;

import static net.time4j.CalendarUnit.MONTHS;
import static net.time4j.PlainDate.DAY_OF_MONTH;
import static net.time4j.PlainDate.DAY_OF_WEEK;
import static net.time4j.PlainTime.MINUTE_OF_HOUR;
import static net.time4j.Weekday.WEDNESDAY;

public class Demo {
  public static void main(String... args) {
	// What is the last day of overnext month?
		SystemClock.inLocalView().today().plus(2, MONTHS).with(DAY_OF_MONTH.maximized()));

	// When is next wednesday?
	PlainDate today = SystemClock.inLocalView().today();
	PlainDate nextWednesday = today.with(DAY_OF_WEEK.setToNext(WEDNESDAY));

	// What is the current wall time rounded down to multiples of 5 minutes?
	PlainTimestamp currentLocalTimestamp = SystemClock.inZonalView(EUROPE.BERLIN).now();
	PlainTime roundedTime =
		currentLocalTimestamp.getWallTime() // T22:06:52,688
		.with(MINUTE_OF_HOUR.atFloor()) // T22:06
		.with(MINUTE_OF_HOUR.roundedDown(5)); // T22:05
	System.out.println("Rounded wall time: " + roundedTime);
	// Example for flexible dayperiods
	PlainTime eveningTime = PlainTime.of(20, 45);
	ChronoFormatter<PlainTime> formatter =
		ChronoFormatter.ofTimePattern("h:mm B", PatternType.CLDR, Locale.ENGLISH);
		"12-hour-format with dayperiod: " 
		+ formatter.format(eveningTime)); // 8:45 in the evening

	// How does last UTC-leapsecond look like in Japan?
	Moment leapsecondUTC =
		PlainDate.of(2012, Month.JUNE, 30)
		.at(PlainTime.midnightAtEndOfDay()) // 2012-06-30T24 => 2012-07-01T00
		.atUTC().minus(1, SI.SECONDS);
	System.out.println(leapsecondUTC); // 2012-06-30T23:59:60Z

		"Japan-Time: "
		+ ChronoFormatter.ofMomentPattern(
	); // Japan-Time: 2012-07-01T08:59:60+0900

	// duration in seconds normalized to hours, minutes and seconds
	Duration<ClockUnit> dur = Duration.of(337540, ClockUnit.SECONDS).with(Duration.STD_CLOCK_PERIOD);

	// custom duration format => hh:mm:ss
	String s1 = Duration.Formatter.ofPattern(ClockUnit.class, "hh:mm:ss").format(dur);
	System.out.println(s1); // output: 93:45:40

	// localized duration format for french
	String s2 = PrettyTime.of(Locale.FRANCE).print(dur, TextWidth.WIDE);
	System.out.println(s2); // output: 93 heures, 45 minutes et 40 secondes
	// following code requires v4.20 (or later) and Java-8 using java.time.LocalDate
	ChronoFormatter<LocalDate> formatter2 =
	    ChronoFormatter.setUp(PlainDate.threeten(), new Locale("en", "SE"))
	        .addPattern("GGGG yyyy, MMMM ", PatternType.CLDR)
	System.out.println(formatter2.format(LocalDate.of(1712, 3, 11)));
	// output: Anno Domini 1712, February 30th

Design remarks:

a) Type-safety: Although Time4J is strongly generified users will not really use any generics in their application code as demonstrated in example code, but are more or less type-safe at compile-time. For example, it is impossible to add clock units to a calendar date. This is in contrast to JSR-310 which heavily relies on runtime exceptions. Otherwise Time4J shares the advantages like immutability and non-tolerant null-handling.

b) Explicit: In contrast to most other libraries Time4J does not like implicit defaults. Users have to explicitly specify what locale or time zone they want. And even if they want the default then they spell it so in methods like: inLocalView() or localFormatter(...) or inStdTimezone(). This philosophy is also the reason why the class PlainDate is missing a static method like today(). This method instead exists in the class ZonalClock making clear that you cannot achieve the current local date and time without specifying the time zone.

c) Manipulations based on elements: Time4J offers a lot of manipulations of date and time by an element-centric approach. Every basic type registers some elements (similar to fields in other libraries) which serve as access key to chronological partial data. These elements like "MINUTE_OF_HOUR" offer many different manipulation methods, called operators using the strategy pattern idea. With this design it is possible to manipulate a PlainTime in about 179 different ways. Another advantage of this design: Despite the size of features the count of methods in most classes is still not too big, PlainTime has less than 50 methods including the inherited methods from super classes.

d) Temporal arithmetic: Another way of manipulation is date/time-arithmetic along a time axis. All four basic types have their time axis. For example roughly spoken Moment is defined as an elapsed count of SI-seconds since UTC epoch while a calendar date (here: PlainDate) maps dates to julian days - another kind of time axis. The essentials of this time arithmetic are realized via the abstract super class TimePoint. So all four basic types inherit methods like plus(n, units), until(...) etc for supporting adding, subtracting and evaluating durations. Multi-unit-durations are handled by the classes Duration and MachineTime.

e) Global versus local: Time4J rejects the design idea of JSR-310 to separate between "machine time" and "human time". This is considered as artificial. So all four basic types offer both aspects in one. For example a calendar date is simultaneously a human time consisting of several meaningful elements like year, month etc. and also a kind of machine or technical time counter because you can define a single incrementing number represented by julian days. In a similar way a UTC-moment has both a technical counter (the number of SI-seconds since UTC-epoch) AND a human representation visible in its canonical output produced by toString()-method (example: 2014-04-21T19:45:30Z). However, Time4J emphasizes the difference between local and global types. Conversion between these types always require a timezone or an offset.

f) Internationalization: Time4J defines its own i18n-resources for many languages (95 languages in version 5.7) in order to defend its i18n-behaviour against poor or insufficient platform resources (which only serve as fallback). Especially localized formatting of durations is not a supported feature on any platform, so Time4J fills an important gap.

g) Powerful format engine: The built-in format engine located in format/expert-package offers overwhelmingly many features, general interfaces for customization and outstanding parsing performance (better than in Joda-Time or JSR-310).

Support for alternative calendars:

  • Badi (Bahai)
  • Chinese (since 1645)
  • Coptic
  • Dangi (old Korean)
  • Ethiopian (including support for Ethiopian time)
  • French revolutionary
  • Hebrew (including support for Hebrew time)
  • Hijri (Islamic) with a lot of customizable variants
  • Hindu (based on algorithms by Dershowitz/Reingold)
  • Historic christian (includes british, byzantine, swedish etc.)
  • Indian national (Saka)
  • Japanese (including lunisolar part since AD 701)
  • Juche (North Korea)
  • Julian
  • Minguo (Taiwan)
  • Persian (3000 years)
  • ThaiSolar (Suriyakati), also valid before 1941
  • Vietnamese

Plans for next releases:

There are no fixed predictions when some features will be introduced in which release. However, you can follow the milestone page to get a rough estimation - see Time4J will be a long-term running project.

Downloads and Requirements:

You can find the latest downloads on the release page for running on the classpath. Alternatively you can use the maven central repository. Maven example for using the timezone repository and running on the module path in Java 9+:

Add these dependencies to your pom-file (typical setup):


Then make sure that the very first usage of Time4J-code starts with the following instruction:


The last step is only necessary for module path environments (Java 9+) provided that the timezone repository should be used instead of platform zone rules. This special initialization can be left out if Time4J is run on the traditional classpath (for example Java 8). Users are also asked to set following system property in OSGi-environments: "-Dnet.time4j.base.useClassloaderOnly=true".

Please also read the installation notes on Time4J-tutorial.


Feedback is welcome. You can best use following page for feedback:


English tutorials and code examples are presented on the website "".


If you are capable of German language you can also read my blog "" where I sometimes post my views about Java and Time, for example my review of JSR-310.

  • Initialization error on startup (Android)

    Initialization error on startup (Android)

    Hi! Getting this crash rarely while calling ApplicationStarter.initialize(this, true); on App.onCreate:

      at net.time4j.format.Attributes$ (
      at net.time4j.format.Attributes$Builder.set (
      at net.time4j.format.Attributes$Builder.set (
      at net.time4j.format.Attributes$Builder.set (
      at net.time4j.format.Attributes$Builder.set (
      at net.time4j.format.Attributes$Builder.setAll (
      at net.time4j.format.Attributes$Builder.setInternal (
      at net.time4j.format.Attributes$Builder.setLanguage (
      at net.time4j.format.Attributes$Builder.setTimezone (
      at (
      at (
      at (
      at (
      at (
      at (
      at (
      at (
      at (
      at (
      at (
      at (
      at (
      at (
      at (
      at (
      at<init> (
      at<init> (
      at$Builder.access$100 (
      at$Builder.access$400 (
      at$Builder.access$500 (
      at$Builder.addCustomized (
      at$Builder.addDayPeriodApproximate (
      at$Builder.addFixedInteger (
      at$Builder.addFraction (
      at$Builder.addInteger (
      at$Builder.addInteger (
      at$Builder.addLiteral (
      at$Builder.addLiteral (
      at$Builder.addLiteral (
      at$Builder.addLiteralChars (
      at$Builder.addNumber (
      at$Builder.addNumber (
      at$Builder.addPattern (
      at$Builder.addProcessor (
      at$Builder.addText (
      at$Builder.addText (
      at$Builder.addTimezoneOffset (
      at$Builder.addYear (
      at$ (
      at$Builder.checkAttribute (
      at$Builder.ensureOnlyOneFractional (
      at$Builder.findDayPeriodElement (
      at$Builder.getLevel (
      at$Builder.skipUnknown (
      at$Builder.startOptionalSection (
      at$Builder.startSection (
      at$Builder.startSection (
      at$Builder.startSection (
      at$ (
      at$1000 (
      at$1100 (
      at$700 (
      at (
      at (
      at (
      at (
      at (
      at (
      at (
      at (
      at (
      at (
      at (
      at (
      at (
      at (
      at (
      at (
      at (
      at (
      at (
      at (
      at (
      at (
      at (
      at (
      at (
      at (
      at (
      at (
      at (
      at$ (
      at (

    Currently, the affected android versions are 6.0 and 7.0. The crash is obtained from the Google Play developer console. I will update if the issue spread more widely. The library version is net.time4j:time4j-android:4.4.4-2019c

    Thanks in advance.

    bug fixed time4a 
    opened by aazhevsky 32
  • Support Badi calendar

    Support Badi calendar

    See also Wikipedia and the proposal for


    Reingold/Dershowitz described the calendar, too (as Bahai calendar).

    enhancement fixed 
    opened by MenoData 16
  • Throwing IllegalArgumentException in background thread of ApplicationStarter

    Throwing IllegalArgumentException in background thread of ApplicationStarter

    We have received an exception as below:

    1. at (
    2. at (
    3. at (
    4. at$1000 (
       or                     .access$1100 (
       or                     .access$700 (
       or                     .addPattern (
       or                     .checkConsistency (
       or                     .display (
       or                     .format (
       or                     .format0 (
       or                     .formatToBuffer (
       or                     .freeze (
       or                     .getChronology (
       or                     .getReason (
       or                     .isEqual (
       or                     .ofDatePattern (
       or                     .ofMomentStyle (
       or                     .ofPattern (
       or                     .parse (
       or                     .parseElements (
       or                     .print (
       or                     .rfc1123DateTime (
       or                     .setUp (
       or                     .sub (
       or                     .updateSelf (
       or                     .with (
       or                     .withTimezone (
    5. at (
    6. at$ (
    7. at (

    It sounds like the exception is thrown in background thread of class (line 153) when tries to format the current moment:


    We are wondering if you have any idea why this happens? Please let us know if you require any further information. Thanks again for your kind help!

    bug fixed time4a 
    opened by iamcalendar 14
  • Time4J in Karaf (OSGI)

    Time4J in Karaf (OSGI)

    Hello everyone! I'm trying to use Time4J in my OSGI-project for sunrise/sunset times calculation. I faced with such a problem. When I try to perform Optional<Moment> result = PlainDate.nowInSystemTime().get(solarTime.sunrise()); I catched java.lang.IllegalStateException: Leap seconds are not supported by configuration (full stacktrace is below). I've tried to explore the sources, but haven't found the root cause.

    Could you tell me, what does this exception mean and how I can fix this, please?

    java.lang.IllegalStateException: Leap seconds are not supported by configuration.
    	at net.time4j.Moment.<init>(
    	at net.time4j.Moment.of(
    	at net.time4j.calendar.astro.SolarTime.fromLocalEvent(
    	at net.time4j.calendar.astro.StdSolarCalculator$2.event(
    	at net.time4j.calendar.astro.StdSolarCalculator$2.sunrise(
    	at net.time4j.calendar.astro.SolarTime.lambda$sunrise$14(
    	at net.time4j.engine.ChronoEntity.get(
    	at com.echelon.cms.core.time4j.Solaris.calculateSunrise(
    	at com.echelon.cms.core.time4j.Solaris.getSolarTiming(
    	at com.echelon.cms.core.scheduler.GeolocationResolverImpl.getRealtimeForGroup(
    	at com.echelon.cms.core.scheduler.GeolocationResolverImpl.resolve(
    	at com.echelon.cms.core.scheduler.SchedulerServiceImpl.schedule(
    	at com.echelon.cms.core.scheduler.SchedulerServiceImpl.schedule(
    	at Proxy8489adbf_812d_4d07_b748_0ce7d5facd25.schedule(Unknown Source)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)[:1.8.0_144]
    	at sun.reflect.NativeMethodAccessorImpl.invoke([:1.8.0_144]
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke([:1.8.0_144]
    	at java.lang.reflect.Method.invoke([:1.8.0_144]
    	at org.apache.cxf.service.invoker.AbstractInvoker.performInvocation([61:org.apache.cxf.cxf-core:3.1.9]
    	at org.apache.cxf.service.invoker.AbstractInvoker.invoke([61:org.apache.cxf.cxf-core:3.1.9]
    	at org.apache.cxf.jaxrs.JAXRSInvoker.invoke([74:org.apache.cxf.cxf-rt-frontend-jaxrs:3.1.9]
    	at org.apache.cxf.jaxrs.JAXRSInvoker.invoke([74:org.apache.cxf.cxf-rt-frontend-jaxrs:3.1.9]
    	at org.apache.cxf.interceptor.ServiceInvokerInterceptor$[61:org.apache.cxf.cxf-core:3.1.9]
    	at org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage([61:org.apache.cxf.cxf-core:3.1.9]
    	at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept([61:org.apache.cxf.cxf-core:3.1.9]
    	at org.apache.cxf.transport.ChainInitiationObserver.onMessage([61:org.apache.cxf.cxf-core:3.1.9]
    	at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke([86:org.apache.cxf.cxf-rt-transports-http:3.1.9]
    	at org.apache.cxf.transport.servlet.ServletController.invokeDestination([86:org.apache.cxf.cxf-rt-transports-http:3.1.9]
    	at org.apache.cxf.transport.servlet.ServletController.invoke([86:org.apache.cxf.cxf-rt-transports-http:3.1.9]
    	at org.apache.cxf.transport.servlet.ServletController.invoke([86:org.apache.cxf.cxf-rt-transports-http:3.1.9]
    	at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke([86:org.apache.cxf.cxf-rt-transports-http:3.1.9]
    	at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest([86:org.apache.cxf.cxf-rt-transports-http:3.1.9]
    	at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPut([86:org.apache.cxf.cxf-rt-transports-http:3.1.9]
    	at javax.servlet.http.HttpServlet.service([21:javax.servlet-api:3.1.0]
    	at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service([86:org.apache.cxf.cxf-rt-transports-http:3.1.9]
    	at org.eclipse.jetty.servlet.ServletHolder.handle([186:org.eclipse.jetty.servlet:9.2.19.v20160908]
    	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter([186:org.eclipse.jetty.servlet:9.2.19.v20160908]
    	at com.echelon.cms.web.filters.CacheFilter.doFilter([233:com.echelon.cms.web.echelon-web-rest:2.20.2]
    	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter([186:org.eclipse.jetty.servlet:9.2.19.v20160908]
    	at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter([246:org.apache.shiro.web:1.3.2]
    	at org.apache.shiro.web.servlet.AdviceFilter.executeChain([246:org.apache.shiro.web:1.3.2]
    	at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal([246:org.apache.shiro.web:1.3.2]
    	at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter([246:org.apache.shiro.web:1.3.2]
    	at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter([246:org.apache.shiro.web:1.3.2]
    	at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain([246:org.apache.shiro.web:1.3.2]
    	at org.apache.shiro.web.servlet.AbstractShiroFilter$[246:org.apache.shiro.web:1.3.2]
    	at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal([246:org.apache.shiro.web:1.3.2]
    	at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter([246:org.apache.shiro.web:1.3.2]
    	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter([186:org.eclipse.jetty.servlet:9.2.19.v20160908]
    	at org.eclipse.jetty.servlet.ServletHandler.doHandle([186:org.eclipse.jetty.servlet:9.2.19.v20160908]
    	at org.ops4j.pax.web.service.jetty.internal.HttpServiceServletHandler.doHandle([216:org.ops4j.pax.web.pax-web-jetty:4.3.0]
    	at org.eclipse.jetty.server.handler.ScopedHandler.handle([185:org.eclipse.jetty.server:9.2.19.v20160908]
    	at org.eclipse.jetty.server.session.SessionHandler.doHandle([185:org.eclipse.jetty.server:9.2.19.v20160908]
    	at org.eclipse.jetty.server.handler.ContextHandler.doHandle([185:org.eclipse.jetty.server:9.2.19.v20160908]
    	at org.ops4j.pax.web.service.jetty.internal.HttpServiceContext.doHandle([216:org.ops4j.pax.web.pax-web-jetty:4.3.0]
    	at org.eclipse.jetty.servlet.ServletHandler.doScope([186:org.eclipse.jetty.servlet:9.2.19.v20160908]
    	at org.eclipse.jetty.server.session.SessionHandler.doScope([185:org.eclipse.jetty.server:9.2.19.v20160908]
    	at org.eclipse.jetty.server.handler.ContextHandler.doScope([185:org.eclipse.jetty.server:9.2.19.v20160908]
    	at org.eclipse.jetty.server.handler.ScopedHandler.handle([185:org.eclipse.jetty.server:9.2.19.v20160908]
    	at org.ops4j.pax.web.service.jetty.internal.JettyServerHandlerCollection.handle([216:org.ops4j.pax.web.pax-web-jetty:4.3.0]
    	at org.eclipse.jetty.server.handler.HandlerWrapper.handle([185:org.eclipse.jetty.server:9.2.19.v20160908]
    	at org.eclipse.jetty.server.Server.handle([185:org.eclipse.jetty.server:9.2.19.v20160908]
    	at org.eclipse.jetty.server.HttpChannel.handle([185:org.eclipse.jetty.server:9.2.19.v20160908]
    	at org.eclipse.jetty.server.HttpConnection.onFillable([185:org.eclipse.jetty.server:9.2.19.v20160908]
    	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob([188:org.eclipse.jetty.util:9.2.19.v20160908]
    	at org.eclipse.jetty.util.thread.QueuedThreadPool$[188:org.eclipse.jetty.util:9.2.19.v20160908]
    opened by AndyMurgin 14
  • Problem unit testing Time4A 3.24-2016i

    Problem unit testing Time4A 3.24-2016i

    I'm not entirely sure whether this has been triggered by a change in Time4A or Android Studio (maybe gradle?), but I'm now having another problem unit testing code like this:

    ChronoFormatter<PlainDate> formatter = ChronoFormatter.ofDateStyle(DisplayMode.LONG, Locale.getDefault());

    (The above code can be in the unit test itself: it doesn't need to be called in some other code).

    I end up with a stack trace that looks like this:

    java.lang.ExceptionInInitializerError at<clinit>(Unknown Source) at$Builder.startSection(Unknown Source) at Source) at Source) at Source) at Source) at$Builder.addPattern(Unknown Source) at Source) at Source) at Source) at at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke( at sun.reflect.DelegatingMethodAccessorImpl.invoke( at java.lang.reflect.Method.invoke( at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall( at at org.junit.runners.model.FrameworkMethod.invokeExplosively( at org.junit.internal.runners.statements.InvokeMethod.evaluate( at org.junit.runners.ParentRunner.runLeaf( at org.junit.runners.BlockJUnit4ClassRunner.runChild( at org.junit.runners.BlockJUnit4ClassRunner.runChild( at org.junit.runners.ParentRunner$ at org.junit.runners.ParentRunner$1.schedule( at org.junit.runners.ParentRunner.runChildren( at org.junit.runners.ParentRunner.access$000( at org.junit.runners.ParentRunner$2.evaluate( at at org.junit.runners.Suite.runChild( at org.junit.runners.Suite.runChild( at org.junit.runners.ParentRunner$ at org.junit.runners.ParentRunner$1.schedule( at org.junit.runners.ParentRunner.runChildren( at org.junit.runners.ParentRunner.access$000( at org.junit.runners.ParentRunner$2.evaluate( at at at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs( at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs( at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart( at com.intellij.rt.execution.junit.JUnitStarter.main( at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke( at sun.reflect.DelegatingMethodAccessorImpl.invoke( at java.lang.reflect.Method.invoke( at com.intellij.rt.execution.application.AppMain.main( Caused by: java.util.MissingResourceException: Can't find bundle for base name numbers/symbol, locale at java.util.ResourceBundle.throwMissingResourceException( at java.util.ResourceBundle.getBundleImpl( at java.util.ResourceBundle.getBundle( at net.time4j.i18n.SymbolProviderSPI.<clinit>(Unknown Source) ... 46 more

    It's entirely possible that I'm just not initializing the library properly, but I've tried everything I can think of (not that I know of a lot of tricks at this point) to get that working in a unit testing context, without success.

    I do know that the last time I looked at this code, I didn't have this problem. So something has changed to break it, but I'm not sure what. I did just now create a completely fresh project that does nothing but add Time4A as a dependency and adds the above line to the unit test, so I know it's not something specific to the rest of my project.

    Is there something I'm missing, or is this a bug?


    question time4a 
    opened by pickscrape 13
  • Introduce day periods with appropriate translations

    Introduce day periods with appropriate translations

    CLDR 28 has introduced a new concept for supporting day periods (including new pattern symbols "b" and "B"). See also:

    Time4J might introduce a new class DayPeriod which can act as ChronoFunction<PlainTime,String> and offer options how to get the concrete time span and i18n-translation for a given time of day.

    enhancement fixed priority: high 
    opened by MenoData 9
  • Support Hindu calendars (modern)

    Support Hindu calendars (modern)



    Dershovitz/Reingold also offers a valuable source of algorithms.

    enhancement fixed 
    opened by MenoData 8
  • Throwing MissingResourceException in background thread of ApplicationStarter

    Throwing MissingResourceException in background thread of ApplicationStarter

    We have received an exception as below:

    1.   at net.time4j.i18n.IsoTextProviderSPI.months (
    2.   at net.time4j.i18n.IsoTextProviderSPI.months (
    3.   at net.time4j.format.CalendarText.getMonths (
    4.   at net.time4j.format.CalendarText.<init> (
    5.   at net.time4j.format.CalendarText.getInstance (
    6.   at net.time4j.DayPeriod.loadTextForms (
    7.   at net.time4j.DayPeriod.of (
    8.   at net.time4j.DayPeriod$Extension.from (
    9.   at net.time4j.DayPeriod$Extension.getElements (
    10.   at<init> (
    11.   at<init> (
    12.   at<init> (
    13.   at$ (
    14.   at$ (
    15.   at (
    16.   at (
    17.   at (
    18.   at (
    19.   at (
    20.   at<init> (
    21.   at<init> (
    22.   at$ (
    23.   at$ (
    24.   at (
    25.   at$ (

    We are wondering if you have any idea why this happens? The version of Time4A is 3.44.3-2018e. Please let us know if you require any further information. Thanks again for your kind help!

    bug time4a 
    opened by iamcalendar 8
  • Throwing IllegalArgumentException while formatting minimum date of Minguo calendar

    Throwing IllegalArgumentException while formatting minimum date of Minguo calendar

    After running the following code

    CalendarSystem<MinguoCalendar> calsys = MinguoCalendar.axis().getCalendarSystem();
    MinguoCalendar minDate = calsys.transform(calsys.getMinimumSinceUTC()); // BEFORE_ROC-1000001911-01-01
    ChronoFormatter<MinguoCalendar> formatter = ChronoFormatter
            .ofPattern("yyyy", PatternType.CLDR, Locale.ENGLISH, MinguoCalendar.axis());

    we get

    IllegalArgumentException: Element YEAR_OF_ERA cannot be printed as the formatted value 1000001911 exceeds the maximum width of 9.

    while expecting 1000001911 as output (because minDate is formattable).

    We suggest to change the minimum date of Minguo calendar to BEFORE_ROC-999999999-01-01

    In other word, we suggest to override getMinimumSinceUTC method of MinguoCalendar class as

    public long getMinimumSinceUTC() {
        return -365242521549; // BEFORE_ROC-999999999-01-01
    bug fixed update 
    opened by iamcalendar 8
  • Not a complete list of time zones and their aliases

    Not a complete list of time zones and their aliases

    In our android project we use WinZoneProviderSPI.NAME_BASED_MAP for converting the iana timeszone to windows. But we are forced to use a crutch like this, because on some devices the timeszone is determined by its alias. Link on source Wiki. The first value is something that is not in the library but is an alias, the second value is what is.

    Map<String, String> aliasMap = new HashMap<>(); aliasMap.put("Asia/Ho_Chi_Minh", "Asia/Saigon"); aliasMap.put("America/Kentucky/Louisville", "America/Louisville"); aliasMap.put("Pacific/Pohnpei", "Pacific/Ponape"); aliasMap.put("America/Atikokan", "America/Coral_Harbour"); aliasMap.put("America/Argentina/Buenos_Aires", "America/Buenos_Aires"); aliasMap.put("America/Indiana/Indianapolis", "America/Indianapolis"); aliasMap.put("America/Argentina/Jujuy", "America/Jujuy"); aliasMap.put("Asia/Kathmandu", "Asia/Katmandu"); aliasMap.put("Pacific/Chuuk", "Pacific/Truk"); aliasMap.put("America/Argentina/Mendoza", "America/Mendoza"); aliasMap.put("Atlantic/Faroe", "Atlantic/Faeroe"); aliasMap.put("Asia/Yangon", "Asia/Rangoon"); aliasMap.put("America/Argentina/Cordoba", "America/Cordoba"); aliasMap.put("Asia/Kolkata", "Asia/Calcutta"); aliasMap.put("America/Argentina/Catamarca", "America/Catamarca"); aliasMap.put("America/Argentina/ComodRivadavia", "America/Catamarca"); aliasMap.put("Europe/Tiraspol", "Europe/Chisinau"); aliasMap.put("America/Ensenada", "America/Tijuana"); aliasMap.put("America/Fort_Wayne", "America/Indianapolis"); aliasMap.put("America/Porto_Acre", "America/Rio_Branco"); aliasMap.put("Asia/Tel_Aviv", "Asia/Jerusalem"); aliasMap.put("Asia/Ulan_Bator", "Asia/Ulaanbaatar"); aliasMap.put("Antarctica/South_Pole", "Pacific/Auckland"); aliasMap.put("Asia/Kashgar", "Asia/Urumqi"); aliasMap.put("America/Rosario", "America/Cordoba"); aliasMap.put("Asia/Dacca", "Asia/Dhaka"); aliasMap.put("Australia/Yancowinna", "Australia/Broken_Hill"); aliasMap.put("Asia/Ashkhabad", "Asia/Ashgabat"); aliasMap.put("America/Virgin", "America/Port_of_Spain"); aliasMap.put("Asia/Harbin", "Asia/Shanghai"); aliasMap.put("Asia/Macao", "Asia/Macau"); aliasMap.put("Asia/Thimbu", "Asia/Thimphu"); aliasMap.put("Australia/Canberra", "Australia/Sydney"); aliasMap.put("Atlantic/Jan_Mayen", "Europe/Oslo"); aliasMap.put("Asia/Chungking", "Asia/Shanghai"); aliasMap.put("Asia/Chongqing", "Asia/Shanghai"); aliasMap.put("America/Atka", "America/Adak"); aliasMap.put("Europe/Belfast", "Europe/London"); aliasMap.put("Pacific/Yap", "Pacific/Truk"); aliasMap.put("Africa/Timbuktu", "Africa/Abidjan"); aliasMap.put("America/Shiprock", "America/Denver"); aliasMap.put("Asia/Ujung_Pandang", "Asia/Makassar");

    enhancement question fixed time4a 
    opened by AlexKnyazyk 8
  • 3.18-2016c appears to make testing difficult (Android)

    3.18-2016c appears to make testing difficult (Android)

    I'm not entirely sure what the reasons are behind this, but I've not been able to get Android tests involving time4j working with 3.18-2016c. The test spinners just sit there: my guess is it's getting confused by the initialization taking place on a different thread?

    Flipping the second parameter of ApplicationStarter.initialize to false causes tests that reference time4j classes to fail with stack traces beginning:

        at$LazyExtensions.iterator(Unknown Source)
        at net.time4j.PlainDate.registerExtensions(Unknown Source)
        at net.time4j.PlainDate.<clinit>(Unknown Source)

    Downgrading to 3.17-2016b fixes the problem completely.

    bug fixed priority: high time4a 
    opened by pickscrape 8
  • Time4J-ui based on JavaFX needed as an extra project

    Time4J-ui based on JavaFX needed as an extra project

    The module time4j-ui which relies on JavaFX cannot any longer run in Java-environments starting with Java 11 because the FX-component was removed from standard Java. Hence it is appropriate

    a) to remove the module time4j-ui from existing modular time4j-project and b) to change time4j-ui to an extra project named time4j-fx for environments where users have installed JavaFX. This approach is comparable with the timezone extension project tzdata and can better deploy special maven build plugins.

    Step a) will be done with version v5.8.1.

    opened by MenoData 0
  • Multiple relative times and day after tomorrow/day before yesterday in PrettyTime

    Multiple relative times and day after tomorrow/day before yesterday in PrettyTime

    Hi MenoData,

    Great library with support! I had a couple of questions.

    import net.time4j.PrettyTime;
    import java.time.ZonedDateTime;
    import java.util.Locale;
    ZonedDateTime time =;

    The result would now be "last [nameOfWeekDay]", but it would be nice to have "day before yesterday".

    • Would it be possible/good to have an extra method in the PrettyTime class for 'day before yesterday' and 'day after tomorrow'?

    • Is it possible to get a list of possible PrettyTime relatives instead of the one? So in the example above, you might get both "last [nameOfWeekDay]" and "day before yesterday". The same could go for saying something happened "last month", "1 month ago" or "last [nameOfMonth]".

    opened by Barachia 2
  • Hebrew calendar and Jewish holidays,

    Hebrew calendar and Jewish holidays,

    1. I suggest adding the Jewish holidays to the Hebrew calendar. I know it is quite complicated. I could help with advice and consultation with calendar experts.
    2. I disagree with the statement "The civil Hebrew day starts at 18:00 o'clock on the previous day." The banking day in Israel starts at 18:30 on weekdays, 14:00 on Fridays, unless they are holidays. Sunday is a weekday. The banking day is legally the business day unless specified differently. Before 2006 the banking day started at 15:00. Where the Hebrew calendar is used for religious purposes is is always sunset. Same outside of Israel, as far as I know.
    opened by rosennej 6
  • Support Bikram-Sambat-calendar (Nepal)

    Support Bikram-Sambat-calendar (Nepal)

    This is the official calendar in Nepal. See also:


    A tabular-based solution is possible but only exists with limited data in the gregorian year range 1934-2023. An astronomical solution based on old hindu calendar as published in "Calendrical calculations" (Dershowitz/Reingold) should be evaluated, too.

    This solar calendar needs to be distinguished from the lunar calendar called "Nepal Sambat". Latter one is used for the calculation of festivals/holidays.

    opened by MenoData 4
  • Generator-API for CLDR-patterns of date and time

    Generator-API for CLDR-patterns of date and time

    The CLDR-data have skeleton pattern entries which allow to generate patterns for date and time just based on locale, text width and a choice of "skeleton" identifiers (ruling which date-time-elements shall be used). Example from German data:

    -<dateTimeFormatLength type="full">
    <pattern>{1} 'um' {0}</pattern>
    -<dateTimeFormatLength type="long">
    <pattern>{1} 'um' {0}</pattern>
    -<dateTimeFormatLength type="medium">
    <pattern>{1}, {0}</pattern>
    -<dateTimeFormatLength type="short">
    <pattern>{1}, {0}</pattern>
    <dateFormatItem id="Bh">h B</dateFormatItem>
    <dateFormatItem id="Bhm">h:mm B</dateFormatItem>
    <dateFormatItem id="Bhms">h:mm:ss B</dateFormatItem>
    <dateFormatItem id="d">d</dateFormatItem>
    <dateFormatItem id="E">ccc</dateFormatItem>
    <dateFormatItem id="EBhm">E h:mm B</dateFormatItem>
    <dateFormatItem id="EBhms">E h:mm:ss B</dateFormatItem>
    <dateFormatItem id="Ed">E, d.</dateFormatItem>
    <dateFormatItem id="Ehm">E h:mm a</dateFormatItem>
    <dateFormatItem id="EHm">E, HH:mm</dateFormatItem>
    <dateFormatItem id="Ehms">E, h:mm:ss a</dateFormatItem>
    <dateFormatItem id="EHms">E, HH:mm:ss</dateFormatItem>
    <dateFormatItem id="Gy">y G</dateFormatItem>
    <dateFormatItem id="GyMMM">MMM y G</dateFormatItem>
    <dateFormatItem id="GyMMMd">d. MMM y G</dateFormatItem>
    <dateFormatItem id="GyMMMEd">E, d. MMM y G</dateFormatItem>
    <dateFormatItem id="h">h 'Uhr' a</dateFormatItem>
    <dateFormatItem id="H">HH 'Uhr'</dateFormatItem>
    <dateFormatItem id="hm">h:mm a</dateFormatItem>
    <dateFormatItem id="Hm">HH:mm</dateFormatItem>
    <dateFormatItem id="hms">h:mm:ss a</dateFormatItem>
    <dateFormatItem id="Hms">HH:mm:ss</dateFormatItem>

    The skeleton identifiers might be modelled as enums which look like DateSkeleton.YMD or TimeSkeleton.HMSA and can be used either just for date or time patterns or can be combined by and(...)-methods to form date-time-patterns using a generator-method like createPattern(Locale, TextWidth).

    opened by MenoData 0
Meno Hochschild
Meno Hochschild
Provides additional date-time classes that complement those in JDK 8

ThreeTen-Extra ThreeTen-Extra provides additional date-time classes that complement those in JDK 8. Not every piece of date/time logic is destined for

ThreeTen 361 Jan 8, 2023
A Java library for parsing and building iCalendar data models

iCal4j - iCalendar parser and object model Table of Contents Introduction - What is iCal4j? Setup - Download and installation of iCal4j System require

iCal4j 637 Jan 5, 2023
Backport of functionality based on JSR-310 to Java SE 6 and 7. This is NOT an implementation of JSR-310.

ThreeTen backport project JSR-310 provides a new date and time library for Java SE 8. This project is the backport to Java SE 6 and 7. See the main ho

ThreeTen 541 Jan 8, 2023
This is a picker view for android , support linkage effect, timepicker and optionspicker

This is a picker view for android , support linkage effect, timepicker and optionspicker

Bigkoo 13.2k Jan 3, 2023
Joda-Time is the widely used replacement for the Java date and time classes prior to Java SE 8.

Joda-Time Joda-Time provides a quality replacement for the Java date and time classes. The design allows for multiple calendar systems, while still pr 4.9k Dec 27, 2022
This service checks the Co-WIN public API at a specific interval and send update to users specified telegram bot.

COVID VACCINE TELEGRAM BOT USING SPRING BOOT This application is a covid vaccine slot notifier via telegram bot. This application uses public CO-WIN A

Hardeek Sharma 6 Oct 4, 2022
Light Chinese Bible is a Mobile app created by Android and SQLite.

About Light Chinese Bible Light Chinese Bible is a Mobile app created by Android and SQLite. It allows you to read the bible on your phone or devices

Pankun (Dennis) Lin 1 Feb 10, 2022
Korean Sentence Splitter

Korean Sentence Splitter Split Korean text into sentences using heuristic algorithm. 1. Installation Maven <dependency> <groupId>io.github.sangdee</

Sangji Lee 37 Oct 28, 2022
Metremenqeemi - Android/iOS app to teach the Coptic Language

ⲙⲉⲧⲣⲉⲙⲛ̀ⲭⲏⲙⲓ The Open Source Android/iOS app to learn how to read and understand the Coptic Language Join our Discord Channel About the Curriculum The

Mark Yacoub 8 Aug 30, 2022
RTL marquee text view android right to left moving text - persian - farsi - arabic - urdo

RtlMarqueeView RTL marquee text view can hande the speed of moving text can jump to the specefic position of the text at start can loop the marquee te

mehran elyasi 4 Feb 14, 2022
Set of support modules for Java 8 datatypes (Optionals, date/time) and features (parameter names)

Overview This is a multi-module umbrella project for Jackson modules needed to support Java 8 features, especially with Jackson 2.x that only requires

FasterXML, LLC 372 Dec 23, 2022
GzKitchen - Japanese Style Restaurant (Mobile App)

GzKitchen-Android GzKitchen - Japanese Style Restaurant (Mobile App) How to copy the project to your local machine : Download / clone tihs repository

Gavriel Satrio Widjaya 3 Jan 9, 2022
Unofficial community-built app for the Japanese language learning tool

jpdb-android Unofficial community-built app for the Japanese language learning tool While the web app works in most scenarios, the goal with

null 3 Feb 15, 2022
Cron utils for parsing, validations and human readable descriptions as well as date/time interoperability.

cron-utils We define crons. And support them. cron-utils is a Java library to define, parse, validate, migrate crons as well as get human readable des

jmrozanec 965 Dec 30, 2022
Provides additional date-time classes that complement those in JDK 8

ThreeTen-Extra ThreeTen-Extra provides additional date-time classes that complement those in JDK 8. Not every piece of date/time logic is destined for

ThreeTen 361 Jan 8, 2023
Easily regenerate worlds at a specific time & date you want (SpigotMC plugin)

Restore/reset worlds at specific times without kicking players from the server! No need to go through the hassle of resetting your worlds manually anymore. Plenty of features are already included in the free version!

Kihsomray 11 Sep 23, 2022
Fork of tagtraum industries' GCViewer. Tagtraum stopped development in 2008, I aim to improve support for Sun's / Oracle's java 1.6+ garbage collector logs (including G1 collector)

GCViewer 1.36 GCViewer is a little tool that visualizes verbose GC output generated by Sun / Oracle, IBM, HP and BEA Java Virtual Machines. It is free

null 4.1k Jan 4, 2023
Fork of tagtraum industries' GCViewer. Tagtraum stopped development in 2008, I aim to improve support for Sun's / Oracle's java 1.6+ garbage collector logs (including G1 collector)

GCViewer 1.36 GCViewer is a little tool that visualizes verbose GC output generated by Sun / Oracle, IBM, HP and BEA Java Virtual Machines. It is free

null 4.1k Jan 4, 2023