DateCalculator is a Java application that can perform three kinds of computation on calendar dates:
DateCalculator uses the Gregorian calendar for all dates, and it accepts input dates between the years 1600 CE and 3999 CE. Dates output by DateCalculator are displayed in user-defined formats. In those formats, the names of days and months may be obtained from a Java locale (a language, or a language and a country) or they may be user-defined.
DateCalculator is made available under two licences:
uk.blankaspect.datecalculator
package (including
resources) may be used under the terms of version 3 of the GNU General Public License.
This section assumes that you have some experience of building and running a Java application.
A Java Development Kit (JDK) that supports Java 17, such as Eclipse Temurin from Adoptium, is required to build DateCalculator.
The src
directory of the repository contains all the source code and
resources that constitute the application; there are no external dependencies. The
directory conforms to the Maven standard directory layout: the source code is in
src/main/java
and the resources are in src/main/resources
.
The supplied Kotlin-DSL-based Gradle
build script, build.gradle.kts
, modifies the compileJava
and
jar
tasks (provided by the java
plug-in) to compile the
application and to create an executable JAR file for it.
The supplied Kotlin-DSL-based Gradle build script, build.gradle.kts
,
defines two tasks that may be used to run DateCalculator:
compileJava
task.
jar
task.
Both tasks extend the JavaExec
task.
When it starts up, DateCalculator is configured with configuration properties that are read from two sources: the command line of the Java launcher and a configuration file whose location may be explicitly specified. If the same property is specified on the command line and in a configuration file, the value from the configuration file takes precedence.
The recommended method of setting the properties in a configuration file is with the Preferences command. For command-line properties, which must be edited manually, the form of the property values is given in an appendix, and it can also be inferred by generating a configuration file with the desired values and inspecting the contents of the file.
When DateCalculator is run, configuration properties may be passed to the
java
launcher on the command line as system properties; eg,
-Dapp.general.mainWindowLocation="100, 0"
. DateCalculator's
command-line configuration properties all have the prefix app.
. A list of
all the properties that are recognised by DateCalculator is given in an appendix.
System properties can be added to the two supplied Gradle
tasks, runMain
and runJar
, with the
systemProperties(Map<String, ?>)
method.
One particular property, app.configDir, is used to specify the directory that contains a configuration file, as described below.
The configuration file is named dateCalculator-config.xml
. DateCalculator
doesn't require a configuration file: it uses a default value for any configuration
property that is missing from the source(s) of configuration. Similarly, if it finds a
property value to be invalid, DateCalculator will display a message to this effect and
use the default value of the property. If the configuration file contains a property
that was specified on the command line, the value from the configuration file is used.
If the configuration has changed when you exit the application normally (ie, using the Exit command or an equivalent), DateCalculator will save its configuration to a configuration file. If a configuration file was read on startup, it will overwrite that file; otherwise, it will write a configuration file to the default directory described above, unless the value of the app.configDir property was an empty string.
A configuration file can be written explicitly with the Save configuration command within the Preferences dialog.
When it starts up, DateCalculator is informed of the location of the configuration file with the app.configDir property. The value of the property may contain special constructs for system properties, environment variables and the user's home directory.
The app.configDir property may be set in two ways:
java
launcher, or
dateCalculator-properties.xml
that resides in the same
directory as the dateCalculator.jar
JAR file.
The dateCalculator-properties.xml
file is a legacy from the time when
DateCalculator was distributed as a JAR file with an installer; the properties file was
written by the installer. If you create a properties file, it should have the following
form, with the example pathname replaced by the actual pathname:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> <properties> <entry key="app.configDir">/home/slothrop/.blankaspect/dateCalculator</entry> </properties>
If the app.configDir property is set both on the command line and in the properties file, the value in the properties file takes precedence.
The existence and value of the app.configDir property determines the locations that are searched for a configuration file:
$PWD
on Linux/UNIX systems, depends on the system and the way in
which DateCalculator was run.
$HOME/.blankaspect/dateCalculator
, where $HOME
is the
environment variable that denotes the user's home directory. On Windows
systems, the default directory is
%APPDATA%\blankaspect\dateCalculator
, where %APPDATA%
is an environment variable.
A Java runtime environment has one or more locales, which are a mechanism by which a Java application can obtain information to adapt itself for different languages and regions — a practice known as localisation. This section describes the few ways in which DateCalculator uses the information provided by locales.
Localisation in DateCalculator is confined to the names of months, the names of days of the week and the identity of the first day of the week. Western numerals — also called Arabic numerals in English — are used exclusively for numbers in dates. More broadly, the user interface has no support for languages that are not written left-to-right, top-to-bottom.
When a Java application starts up, the Java environment sets a default locale, which is determined from the operating system. DateCalculator uses this locale for
A locale may be selected as the source of the names of months and days of the week that are used by DateCalculator's date formats. This locale may be different from the default locale.
DateCalculator uses a pure Gregorian calendar for all dates: there is no point at which dates switch to the Gregorian calendar from its predecessor, the Julian calendar. This simplifies the handling of dates by DateCalculator at the cost of reducing its usefulness for historical dates.
The Gregorian calendar was adopted at different times by different countries and regions. The Wikipedia article on the Gregorian calendar has two pieces of information that allow you to work out, for a given year and country, the number of days that you should subtract from a Gregorian date to convert it to a Julian date:
According to Wikipedia, there were some local complications in the transition from the Julian to the Gregorian calendar, so the conversion between calendars will not be straightforward in all cases.
DateCalculator accepts input dates between the years 1600 CE and 3999 CE, though it will display results outside this range.
DateCalculator uses names of months and days of the week in two places: the date-selection dialog and the formatted dates that are output by the increment and interval functions.
In the date-selection dialog, the names of months and days of the week are those for the default locale. The names of months are abbreviated to the first three or more characters; the names of days are abbreviated to the first two or more characters.
The sources of the formatted dates are described in the section on date formats.
The dates that are output by DateCalculator's increment and interval functions are formatted with one of the user-defined formats. A date format consists of a pattern, which determines how the date will appear, and a name, which is just an alias for the pattern, to allow you to select it more easily from a list.
A pattern can contain two kinds of element: literal text and fields. The formatter leaves literal text unchanged but replaces fields with the appropriate component of the date — year, month or day. The month and day fields can be either a number or a name. The width (number of characters) and alignment (left or right) of a field can be specified. A field whose content is smaller than its specified width will be padded with spaces or, if it is a number field, optionally with zeros. A field whose content is larger than its specified width will be truncated.
For a name field, the names of months and days of the week are obtained either from a selected locale or, if the names from the locale are not acceptable, from lists of user-defined names of months and days of the week. The date.namesSource configuration property determines whether the names are obtained from a locale or whether they're user-defined.
In a pattern, a field starts with a %
character. This may be followed by
the special characters [
or ]
, which denote left and right
alignment respectively, and by a decimal number to denote the width of the field.
(Fields are left-aligned by default, so the left-alignment prefix is unnecessary.) The
field ends with a letter that identifies the kind of field.
A maximum of 64 date formats can be defined. Neither the name nor the pattern of a date
format may contain the string ##
because it is used in the configuration
property as the separator between the name and pattern.
The following tables describe the form and meaning of fields in a pattern:
Field identifiers | |
---|---|
y | year |
m | month (number) |
M | month (name) |
d | day (number) |
D | day (name) |
Field prefixes | |
---|---|
n is a decimal number between 1 and 999 denoting the width of the field in characters | |
% | implicit width |
%n | width n, left-aligned (ie, padded to the right with spaces) |
%0n | width n, padded with leading zeros |
%[n | width n, left-aligned (ie, padded to the right with spaces) |
%]n | width n, right-aligned (ie, padded to the left with spaces) |
Other | |
---|---|
%% | literal % character |
The following examples are all representations of the date 4 October 1986. The names of
months and days of the week are those for the en-GB
locale.
Pattern | Formatted output |
---|---|
%04y-%02m-%02d | 1986-10-04 |
%D, %d %M %y | Saturday, 4 October 1986 |
%2d %3M %y | 4 Oct 1986 |
%m/%d/%y | 10/4/1986 |
"%3D %3M %02d" | "Sat Oct 04" |
%02d/%02m/%02y (%D) | 04/10/86 (Saturday) |
%02d.%02m.%02y [%]10D] | 04.10.86 [ Saturday] |
%2d%%%2m%%%4y | 4%10%1986 |
DateCalculator's main window is equivalent to a dialog box. The size of the window cannot be changed directly, though it may change as a side-effect of changing the fonts in the user preferences.
The main window is tabbed, with a tab for each of the three functions of the application: Increment (adding a number of days to a date or subtracting a number of days from a date), Difference (calculating the number of days between two dates) and Interval (generating a list of dates with a specified number of days between successive pairs of dates).
The increment function adds a number of days to a date or subtracts a number of days from a date.
The Date field, a compound date field, holds the input date. The button to the right of the field brings up a date-selection dialog in which you can select the date. The Today button to its right sets the date to the current date.
The Days spinner specifies the number of days that will be added to or subtracted from the date in the Date field.
The Date format drop-down list selects the format that is used for the result. The items in the list are the names of the date formats. When the list is displayed, the pattern associated with an item in the list is displayed as a tooltip when the mouse cursor hovers over the item.
The result of the calculation is displayed in the Result field. The Copy button to the right of the field copies the result to the system clipboard. The button with an upward-pointing arrow to the right of the Copy button sets the Date field to the result, facilitating chained calculations.
The buttons for the Add and Subtract commands are enabled when none of the three subfields of the Date field is empty. When the Add or Subtract command is issued, the Date field is validated and an error message displayed if the date is invalid. If the date is valid, the addition or subtraction is performed and the Result field is updated with the result.
The difference function calculates the number of days from one date to another.
The Start date and End date fields are compound date fields that hold, respectively, the start and end dates. The button to the right of each field brings up a date-selection dialog in which you can select the date. The Today button to its right sets the date to the current date.
The result of the calculation — the number of days from the start date to the end date — is displayed in the Result field; if the start date is after the end date, the result will be negative. The Copy button to the right of the field copies the result to the system clipboard.
The button for the Subtract command is enabled when none of the subfields of the Start date and End date fields is empty. When the Subtract command is issued, the Start date and End date fields are validated and an error message displayed if either date is invalid. If the dates are valid, the subtraction is performed and the Result field is updated with the result.
The interval function generates a sequence of dates with a given number of days between each successive pair of dates.
The Start date field, a compound date field, holds the first date in the sequence. The button to the right of the field brings up a date-selection dialog in which you can select the date. The Today button to its right sets the date to the current date.
The Interval spinner specifies the number of days between successive dates in the sequence.
There are three ways to specify the end of the sequence:
The choice is controlled by radio buttons, each of which enables its adjacent components when it is selected.
The Date format drop-down list selects the format that is used for the result. The items in the list are the names of the date formats. When the list is displayed, the pattern associated with an item in the list is displayed as a tooltip when the mouse cursor hovers over the item.
The button for the Generate command is enabled when none of the subfields of the Start date field — and the subfields of the End date field, if it is enabled — is empty. When the Generate command is issued, the date fields are validated and an error message displayed if a date is invalid. If the dates are valid, the sequence of dates is generated and displayed in the selected format, one date per line, in a dialog box. In the results dialog, the Copy command copies the list of dates to the system clipboard.
DateCalculator's user interface has some non-standard graphical components and some standard components that have bespoke features.
A spinner is a graphical component for editing a numerical value. It consists of a text field adjacent to a pair of small buttons. The value in the text field may be edited manually, or it may be incremented and decremented by one of the following methods:
Using the last two methods, the amount by which the value is incremented or decremented can be modified by holding down the Ctrl, Shift or Ctrl+Shift keys, which correspond to increments of 10, 100 and 1000 respectively.
A compound date field is a group of three text fields for editing a date. From left to right, the three fields are year, month and day. The three subfields accept only decimal digits: the year field accepts four digits while the month and day fields both accept two digits.
To the right of each compound date field is a button with an icon that is intended to represent a page from a calendar. This button brings up a dialog box in which you can select a date. If there is a valid date in the adjacent compound date field, that date is selected when the dialog is displayed.
The arrow buttons at the top of the dialog are for moving through the months of the calendar: the single-arrow buttons move to the previous or next month; the double-arrow buttons move to the previous or next year.
Between the two sets of arrow buttons is a label indicating the current month and year. (The month is denoted by the first three or more characters of its name.) If you click the left mouse button on the label or press Ctrl+Space, a further dialog box is displayed in which you can edit the month and year.
The main panel of the date-selection dialog has the customary form of a month from a calendar: a table whose columns are the seven days of the week. The headers of the column are the first two or more characters of the names of the days of the week. If you press the left mouse button over a column header, the full name of the day is displayed in a pop-up box.
You can use the left mouse button to select a day from the current month; the selection cursor will follow the mouse cursor as you drag the mouse. Double-clicking on a day will select the date and accept the dialog (ie, it will close the dialog as though the OK command were issued). If the dialog is accepted, the adjacent compound date field will be updated with the selected date.
The following keys can be used to navigate the date-selection dialog:
Left | Select the previous day in the current row |
Right | Select the next day in the current row |
Home | Select the first day in the current row |
End | Select the last day in the current row |
Up | Select the previous day in the current column |
Down | Select the next day in the current column |
Ctrl+Home | Select the first day in the current column |
Ctrl+End | Select the last day in the current column |
PageUp | Move to the previous month |
PageDown | Move to the next month |
Ctrl+PageUp | Move to the previous year |
Ctrl+PageDown | Move to the next year |
Ctrl+Space | Edit the month and year |
DateCalculator's main commands are issued from the buttons at the bottom of its main window. The tabs of the main window have their own commands, which are described in the sections on the Increment tab, Difference tab and Interval tab.
The Preferences command brings up a tabbed dialog box in which the configuration properties of DateCalculator can be edited. The properties on the various tabbed pages are described below.
Yes
, pathnames are displayed in a reduced
"UNIX style" in error messages relating to the configuration file.
A pathname is converted from its platform-specific form in two steps:
~
.
\
on Windows systems) is replaced
by /
.
No
.
Yes
, all the text in a text field will be
automatically selected when the field gains keyboard focus, regardless of how
the focus is transferred.
Yes
.
Yes
, the location of the main window on the screen
will be saved to the configuration file when you exit the application. The next
time that DateCalculator is run, its main window will be positioned at the
previously saved location.
No
.
awt.useSystemAAFontSettings
.
Default
.
No
, the pages of the calendar in the date-selection dialog show only the days of the current
month, with empty spaces in place of the days of the preceding and following
months. If you select Yes
, the days of the adjacent months are
shown greyed.
Yes
.
##
because it is used in the configuration property as
the separator between the name and pattern.
Default
,
with the pattern %04y-%02m-%02d
, is available from Date format drop-down lists.
Locale
is
selected, the names are obtained from the locale specified by the date.namesLocale
configuration property; if User-defined
is selected, the names are
obtained from the user-defined lists of names of months and days of the
week.
Locale
.
Locale
. The drop-down list contains the names of all the
available locales. The names are in an abbreviated form: all locales have a
two-letter, lower-case ISO 639-1 language code
followed in some cases by a hyphen and a two-letter, upper-case ISO
3166-1 country code. (In a few cases, the country code is followed by
another hyphen and a variant code.) At the top of the list is the
special value, <default locale>
, which identifies the default locale.
<default locale>
.
<default>
, the first day of the week will be that for the
default locale, which, for example, is Monday in the UK and Sunday in the USA.
<default>
, which uses the value for the
default locale.
Some of the configuration properties will take effect when the Preferences dialog is accepted (by closing it with OK); other properties (eg, the look-and-feel and fonts) will not take effect until the next time that DateCalculator is run.
The configuration file is normally saved automatically when DateCalculator exits, if the configuration has changed. The Save configuration command in the Preferences dialog can be used to save a configuration file explicitly.
This command terminates the application.
The app.configDir configuration property can contain special constructs for system properties, environment variables and the user's home directory. The special constructs are expanded when the pathname is used.
user.home
)
and environment variables (eg, PATH
) are referenced by enclosing them
between ${
and }
; that is, they must have the form
${<name>}
. A Java system property takes precedence over an
environment variable with the same name.
${user.home}/projects
${HOME}/projects
sys.
to it.
${sys.user.home}/projects
env.
to it.
${env.HOME}/projects
~
in a pathname is expanded into the user's home directory
using the user.home
system property, which is usually equivalent to the
environment variable $HOME
on Linux/UNIX systems or
%USERPROFILE%
on Windows systems.
~/projects
The table below lists the configuration properties of DateCalculator. Apart from the app.configDir property, which, for obvious reasons, cannot be used within a configuration file, all properties can be used in the two configuration locations: command-line properties and configuration file.
When used in a -D
command-line property, app.
must be prefixed
to the property key (eg, app.general.mainWindowLocation).
Any commas (,
) or backslash characters (\
) in the name of a
font must be escaped by prefixing a \
character to them.
In the table below, the initial character of an italicised component of a property value denotes its data type according to the following convention:
i | integer |
p | platform-specific pathname, which may contain special constructs |
s | string |
Property key | Property value |
---|---|
configDir | pPathname |
appearance.showAdjacentMonths | false | true |
appearance.lookAndFeel | sName |
appearance.textAntialiasing | default | none | normal | subpixelHRgb | subpixelHBgr | subpixelVRgb | subpixelVBgr |
date.dayName.<index> | sName |
date.firstDayOfWeek | iIndex |
date.format.<index> | sName##sPattern |
date.monthName.<index> | sName |
date.namesLocale | sLocale |
date.namesSource | locale | userDefined |
font.comboBox | sName, plain | bold | italic | boldItalic, iSize |
font.main | sName, plain | bold | italic | boldItalic, iSize |
font.textField | sName, plain | bold | italic | boldItalic, iSize |
general.mainWindowLocation | iX, iY |
general.selectTextOnFocusGained | false | true |
general.showUnixPathnames | false | true |