How to implement Persian Calendar - java

Is there any implementation of Persian calendar DatePicker on JavaFx?
There is no Persian chronology to use on DatePicker to achieve a Persian calendar

I have now developed a ready-to-use calendar picker which also offers a persian calendar. It was originally inspired by the nice work of Christian Schudt, but completely rewritten and enhanced. Just download my library Time4J-v4.20 (or later, available in Maven) and use this code demo:
CalendarPicker<PersianCalendar> picker = picker.persianWithSystemDefaults();
picker.setLengthOfAnimations(Duration.seconds(0.7));
picker.setShowInfoLabel(true);
picker.setLocale(new Locale("fa", "IR"));
picker.setShowWeeks(true);
picker.setCellCustomizer(
(cell, column, row, model, date) -> {
if (CellCustomizer.isWeekend(column, model)) {
cell.setStyle("-fx-background-color: #FFE0E0;");
cell.setDisable(true);
}
}
);
You can also set other properties like minimum and maximum date. Here an example image using Farsi language and a localized week model for Iran. You can navigate through all Persian months, years or decades (by clicking on the header) or jump to current date (by clicking on the footer).

As it is stated in the docs, you can set the used calendar system via the ObjectProperty<Chronology> of the DatePicker.
The method you need to do so is
public final void setChronology(Chronology value)
As there's no default persian/iranian calendar system (only the hiraj system is implemented) implemented, you have to write your own:
"Adding New Calendars
The set of available chronologies can be extended by applications. Adding a new calendar system requires the writing of an implementation of Chronology, ChronoLocalDate and Era. The majority of the logic specific to the calendar system will be in the ChronoLocalDate implementation. The Chronology implementation acts as a factory.
To permit the discovery of additional chronologies, the ServiceLoader is used. A file must be added to the META-INF/services directory with the name 'java.time.chrono.Chronology' listing the implementation classes. See the ServiceLoader for more details on service loading. For lookup by id or calendarType, the system provided calendars are found first followed by application provided calendars.
Each chronology must define a chronology ID that is unique within the system. If the chronology represents a calendar system defined by the CLDR specification then the calendar type is the concatenation of the CLDR type and, if applicable, the CLDR variant,
Implementation Requirements:
This interface must be implemented with care to ensure other classes operate correctly. All implementations that can be instantiated must be final, immutable and thread-safe. Subclasses should be Serializable wherever possible."
Source: https://docs.oracle.com/javase/8/docs/api/java/time/chrono/Chronology.html?is-external=true

Related

How can I represent and operate on time values greater than 24:00 in Java?

I'm currently doing some work in an application domain that uses time values greater than 24:00 to represent times after midnight that are still associated with the previous day's details. For instance, it might use 25:15 on Monday to represent 1:15 AM on Tuesday, since from a domain standpoint, this value is still associated with Monday's data.
This type of time usage is briefly mentioned in the Wikipedia article for the 24-hour clock:
Time-of-day notations beyond 24:00 (such as 24:01 or 25:00 instead of 00:01 or 01:00) are not commonly used and not covered by the relevant standards. However, they have been used occasionally in some special contexts in [various countries] where business hours extend beyond midnight, such as broadcast television production and scheduling.
Java provides the LocalTime model class to represent times. However, LocalTime is constrained to be between midnight of the given day (inclusive) and midnight the next day (exclusive), i.e. in the range [0:00-23:59:59.999999999].
The Java Time API was written to be flexible, but with more specialized concepts excluded from the core API. As mentioned in the ThreeTen Extra project curated by the primary author of the Java 8 date & time library:
Not every piece of date/time logic is destined for the JDK. Some concepts are too specialized or too bulky to make it in.
I have not had luck finding an existing type or other straightforward way to model this less-constrained time type through the core Java libraries or ThreeTen Extra. It is however, very possible that I'm missing something, perhaps something fairly obvious.
How can I model this sort of less-constrained time in Java, ideally using the java.time API or an extension thereof a la the ThreeTen-Extra project? I would like to be able to use it to textually represent the time value ("25:15") and ideally perform temporal calculations with it (e.g. convert "Monday # 25:15" to "Tuesday # 1:15 AM").
If there isn't a straightforward approach, I'll probably end up opening an issue at the Threeten-Extra project.
My first thought is to store that as a Duration object. You could easily use the getters on that class to construct the HH:mm string when you want to display the value, or use something like the Apache Commons DurationFormatUtils.
The LocalDate and LocalDateTime classes support operations like adding and subtracting Durations.
No that does not exist
I am convinced that no class in the three-ten family or commonly used class from elsewhere supports what you want. The closest my search could get was the DayCycles class of the Time4J library (link at the bottom). It consists of a time of day (a PlainTime) and a count of days relative to an unspecified date, so what you ask for; but it’s specifically for returning the result of adding or subtracting time from a PlainTime and doesn’t offer any functionality of its own.
Spin your own
I wouldn’t think that developing your own class that could interoperate with java.time would be too hard. Likely base it off java.time.Duration as Mark B suggests, depending on more precise requirements.
Parsing and formatting may be the hardest part if you have demanding requirements for these. Possibly it’s worth taking inspiration from the source code for the Joda-Time library since this includes facilities for formatting and parsing durations.
Another source of inspiration would be the source of java.time.LocalTime.
Here are the very first few bits:
public class SpecializedTime {
private Duration timeSince0000;
private SpecializedTime(Duration timeSince0000) {
this.timeSince0000 = timeSince0000;
}
static SpecializedTime parse(String text, DateTimeFormatter formatter) {
ParsePosition position = new ParsePosition(0);
TemporalAccessor parsed = formatter.parseUnresolved(text, position);
if (position.getErrorIndex() != -1) {
throw new DateTimeParseException("Parse error", text, position.getErrorIndex());
}
if (position.getIndex() != text.length()) {
throw new DateTimeParseException("Unparsed text", text, position.getIndex());
}
if (! parsed.isSupported(ChronoField.HOUR_OF_DAY)) {
throw new DateTimeParseException("Cannot resolve", text, 0);
}
Duration time = Duration.ofHours(parsed.getLong(ChronoField.HOUR_OF_DAY));
if (parsed.isSupported(ChronoField.MINUTE_OF_HOUR)) {
int minuteOfHour = parsed.get(ChronoField.MINUTE_OF_HOUR);
// Should validate, 0..59
time = time.plusMinutes(minuteOfHour);
}
// Same for seconds and nanoseconds
return new SpecializedTime(time);
}
#Override
public String toString() {
return String.format("%02d:%02d", timeSince0000.toHours(), timeSince0000.toMinutesPart());
}
}
Demonstration:
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("H:m");
SpecializedTime st = SpecializedTime.parse("25:15", timeFormatter);
System.out.println(st);
Output:
25:15
Link
Documentation of DayCycles form Time4J
There is not currently a type which directly models this concept in ThreeTen-Extra or in the core Java libraries. However, a feature request now exists in ThreeTen-Extra requesting this functionality (threeten-extra#169).
ThreeTen-Extra project maintainer Stephen Colebourne has commented that this would be a sensible addition to the library, so it's seems to be mostly a matter of when or whether anybody steps up to implement the feature.
Stephen Colebourne also suggested a few ways of implementing this feature within the library. One of these suggested approaches could be used as part of a custom solution to this problem.
It could be a combination of LocalTime and a number of days, or something closer to LocalTime. Various design options.

Java Date and Calendar

I'm aware that Java 8 has a much improved date and time library based on Joda Time, but I'm very curious about the decisions made in the old libraries. I haven't found any good explanation about the java.util.Date constructor deprecation rationale (the closest question I've found is this: Difference between new Date() and Calendar date but it doesn't ask about deprecated methods/constructors and doesn't have an accepted answer).
The constructor java.util.Date(year, month, day) is considered deprecated and we should use new GregorianCalendar(year + 1900, month, date). If we call getTime() (which returns a Date...) on the Calendar instance, what have we gained, other than avoiding a deprecated constructor? Even java.sql.Date.toLocalDate uses some deprecated methods internally.
I have a codebase littered with this pattern (new GregorianCalendar followed by getTime) just to avoid the deprecated methods of java.util.Date (I need java.util.Date and java.sql.Date in JPA and JDBC), but I'm not sure what's the point or what was the point back then (*).
(*) Nowadays I can finally change them all to LocalDate because that's what I really needed anyway — saving what the user typed in without any timezone conversions.
See second paragraph in the javadoc of java.util.Date:
Prior to JDK 1.1, the class Date had two additional functions. It allowed the interpretation of dates as year, month, day, hour, minute, and second values. It also allowed the formatting and parsing of date strings. Unfortunately, the API for these functions was not amenable to internationalization. As of JDK 1.1, the Calendar class should be used to convert between dates and time fields and the DateFormat class should be used to format and parse date strings. The corresponding methods in Date are deprecated.
So, to answer your question "What have we gained?", the answer is "support for internationalization":
Ability to specify time zone (using Calendar).
Ability to use non-Gregorian calendar (using Calendar).
Ability to use localized formatting and parsing of date strings (using DateFormat).
The old libraries permitted the construction of java.util.Date items from entries in a Gregorian calendar, by passing in the year, month, day, etc items.
This was problematic for a number of reasons. First, the Gregorian calendar system is a hybrid calendar system that transitioned from the Julian calendar system. This transition included the need to "skip" dates to realign the Julian calendar system with the seasons. So, there are missing days. Surprisingly, the java.util.Date does a decent job of capturing this behavior, except:
The dates to be skipped are dependent on when the transition was adopted, which mostly maps out to be Locale dependent.
The strong binding to the Gregorian Calendar of the core java.util.Date object means that implementing other calendar systems is problematic, as you need to implement them on top of a Gregorian System.
The date being tied to Locale and TimeZone also meant that you had to adjust the platform's Locale and TimeZone to get the appropriate Date behavior you wished, often adjusting it back for out-of local date computations.
The new calendar system attempts to avoid this by:
Having an API that passes in a field to set with the value, preventing direct binding of the calendar fields to the API methods.
Having an API that permits subclassing a Calendar such that one could implement calendars with vastly different definitions of months, days, and years (think lunar calendars, Jewish calendars, Arabic Calendars, Chinese Calendars, etc).
Going forward, one should use java.util.Date only as a thin wrapper around a timestamp, and that's more to have compatibility with the older APIs. All Date manipulations should be done in the appropriate Calendar instance.

Fast way to get the current Calendar object in Java

Given a method that needs to use the values of the current day/month/year on every invocation and which is invoked several (millions or more) times per second, is there any faster way of implementing that functionality, other than creating a Calendar object for the current time on every invocation?
Using Calendar.getInstance() or calendar.setTime() (with time field recalculation) is overly expensive to do many times per second.
Standard Java solutions are preferable (e.g., over using third party libraries).
To get the current date/time, I find that LocalDate.now() is faster than Calendar.getInstance(). The LocalDate class can be found in the java.time package, which is new since Java 8 (Of course, if you want to maintain compatibility with old Java versions, that may not be an option).
The best solution within the scope of standard java (no 3rd party-libraries) is using the class LocalDate. So far this answer is identical to that of #Chronio, but I differ in use. The factory method now() cannot be so quick because it exploits the system timezone - maybe even using a synchronized approach anywhere in the depth of TimeZone.getDefault().
But the class LocalDate is very quick if you use its factory methods with arguments of year, month and day-of-month. Here you are just setting the state members without any timezone calculation and without any calculation of gregorian calendar math (okay only quick year-dependent length-of-month-check is involved). Just see the source code.
use the Date, instead of Calendar class it will give you the current date

Which Android APIs to use for simple date and time functions

The set of date and time functions I need are pretty basic.
An object to represent a date/time (for convenience in function calls).
Conversion functions to and from y,m,d,h,m,s.
Format/parse functions to and from numeric-only localised string representation. Eg dd/mm/yyyy, yyyy-mm-dd, mm.dd.yyyy or whatever order and delimiters are locally expected.
A system function to get the current local date and time (timezones not required).
Compatible with the DatePicker widget.
Thread safe. Static functions available to both UI and worker (NDK) threads.
So far I've found that:
Calendar and GregorianCalendar can do the conversions, but they're clunky to use and they're not thread safe.
SimpleDateFormat can do the formatting, if I could only figure out which magic string to feed it! The default is not numeric.
Time has a nicer set of conversion functions, but has no date/time object and the parse/format functions are documented only indirectly. And it smells a lot more like Unix than Java.
So do I find a way to fix the thread safety and try to persuade SimpleDateFormat to give me what I need? Or do I give up and jump ship to Time? Or have I missed something?
Just to be clear, this is not a request for a library recommendation or a shopping list. It's a request for assistance on how to implement a specific set of functions using the given Android API. I'm looking for an expert on using these libraries to point out a path through the morass. I would hope that a well-written answer would benefit other readers also struggling with this part of Android.
Personally I find Joda-Time to be able to handle almost everything you need for date and time. Since it's just a .jar it should be able to be imported.
Here's how to use it, for the questions you asked specifically:
An object to represent a date/time - DateTime for immutable or MutableDateTime for one that you need to apply transformations to.
These objects have many methods for conversion, see the Joda-Time API for AbstractDateTime as an example, as all of Joda's classes extend AbstractDateTime
You can use String convertedToString = new DateTime().toString("yyyy-MM-dd") to get it as 2014-05-05. To reverse this, use this API: DateTimeFormatter parseDateTime(someStringThatRepresentsADate)
DateTime now = new DateTime() gives you now, as a DateTime object
You can get a DateTime object from several other classes, such as Calendar by doing something like DateTime fromCalendar = new DateTime(myCalendarObject)
See The FAQ for Joda on multi-threading
In order to import Joda into your Android project, assuming you're using Android studio and Gradle, see this answer: Android Studio: Add jar as library?

Is there a DateFormatProvider that will use Windows localization information?

I'm writing a java gui application that has to display dates.
Since this application is primarily going to run on Windows systems, I would like to be able to use date & time formats that correspond to the Windows localization settings.
I found DateFormatProvider class, in Java 6, which gave me high hopes ... but I haven't found an implementation that will use the Windows localization information.
Any suggestions?
You should be able to use the DateFormatProvider methods with the default locale returned by getDefault().
The Java Virtual Machine sets the
default locale during startup based on
the host environment.
EDIT: if you can't just pass the default locale to the DateFormat class, there is example code here for implementation of a concrete class that extends DateFormatProvider.
I haven't heard about any Java date formatter that uses MS Windows formatting routines (or just definitions for that matter). Since Java is meant to be multiplatform (compile once, run anywhere), it simply couldn't use underlying OS behavior, for consistency reasons.
You can use DateFormat class as defined here:
DateFormat dateFormatter = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.getDefault());
String formattedDate = dateFormatter(new Date());
One important issue about this class: LONG date formats are broken for Czech, Polish and Russian, possibly for other Slavic languages too. I recommend using MEDIUM date format instead.
BTW. This will format dates for Gregorian or Julian calendars. It won't give you Arabic nor Hebrew calendars (although former is default for some countries).
Edit
I am not aware of your specific requirements, but since you mentioned Locale, maybe ICU4J's DateFormat class is what you looking for. Still, as per my knowledge (which might be incomplete here), they are using their own formatter and localized text database. However, this database is probably more complete (especially on Mac) than the one bundled with JDK (previous ICU snapshot).

Categories

Resources