Skip to content

Repository files navigation

Rouble rate calculator

CI

A self-contained Java command-line program that downloads official exchange-rate history from the Bank of Russia and calculates arithmetic averages for requested day, week, month or year periods.

The result is expressed as Russian roubles per one unit of the selected currency. Only rates actually published by the CBR are averaged; weekends and other dates without a newly published rate are not filled in.

Downloaded rates are cached in SQLite at ~/.cache/rouble-rate-calculator/rates.db. Set the ROUBLE_RATE_DB environment variable to use another database file. The cache records both rates and fetched date coverage, so weekends and holidays do not look like missing data. When a request has several gaps, the calculator makes one CBR request covering the first through last gap. Historical coverage is reused permanently; today and future dates remain refreshable.

Requirements

  • CLI: JDK 25 or newer and Maven 3.8 or newer
  • Android: JDK 21, Android SDK 36, and Android Build Tools 36.0.0
  • Internet access to www.cbr.ru

The Maven CLI and Android builds currently require different active JDKs. The CLI is compiled with Java 25. The Android build uses Gradle 8.13 and AGP 8.13, which require JDK 17 or newer; this project standardizes its Android builds and app bytecode on Java 21. The current Android toolchain cannot run on Java 25.

Set JAVA_HOME per command, or switch JDKs with your preferred version manager:

JAVA_HOME=/path/to/jdk-25 mvn test
JAVA_HOME=/path/to/jdk-21 ./gradlew test assembleDebug

In Android Studio, set the Gradle JDK to 21 under the Gradle settings. This is independent of the JDK selected in a terminal for Maven or GraalVM.

Build and run

mvn package
java -jar rate-cli/target/rouble-rate-calculator-1.0.0.jar

All parameters are named and optional. The defaults are USD, yesterday's date in Moscow, and a three-month period:

java -jar rate-cli/target/rouble-rate-calculator-1.0.0.jar --currency EUR --end-date 2026-07-31
java -jar rate-cli/target/rouble-rate-calculator-1.0.0.jar --periods 3m,7d,1w,1y
java -jar rate-cli/target/rouble-rate-calculator-1.0.0.jar -c EUR -e 2026-07-31 -p 3m,7d,1w,1y
java -jar rate-cli/target/rouble-rate-calculator-1.0.0.jar -c EUR --today
java -jar rate-cli/target/rouble-rate-calculator-1.0.0.jar -c EUR --start-date 2026-01-01
java -jar rate-cli/target/rouble-rate-calculator-1.0.0.jar -s 2026-01-01 -e 2026-06-30
java -jar rate-cli/target/rouble-rate-calculator-1.0.0.jar -s 2026-01-01 -p 3m

Both --name value and --name=value forms are accepted. Period units are d for days, w for weeks, m for months and y for years. Short forms are -c for currency, -e for end date, and -p for periods. Argument parsing is provided by Picocli.

Use -t or --today to print only the currently effective official rate. The output includes the CBR effective date, which may differ around weekends and holidays. Today's mode cannot be combined with date or period options.

Use -s or --start-date for an explicit interval:

  • Start only: from the start date through yesterday in Moscow.
  • Start and end: the inclusive interval between those dates.
  • Start and one period: from the start date through start plus that period.
  • Start, end, and period together: rejected as ambiguous.

Run with --help to see the command syntax.

CLI output and help are available in English and Russian. By default the app uses the system language when it is Russian and falls back to English for other locales. Select a language explicitly with -l en, --language ru, or the corresponding --language=... form. Option names, currency codes, ISO input dates, and period syntax remain language-independent.

Run the unit tests with:

mvn test

Native executable with GraalVM CE

Install GraalVM Community Edition 25 with the native-image tool, make it the active JDK, and run:

mvn -Pnative clean package
./rate-cli/target/rouble-rate-calculator

The native executable accepts the same named options:

./rate-cli/target/rouble-rate-calculator --currency EUR --periods 3m,7d,1w,1y

Data source: the Bank of Russia XML_daily.asp and XML_dynamic.asp endpoints.

Android app

The Android application lives in android-app and consumes the same rate-core and rate-cbr sources through the Gradle multi-project build. Its Compose screen accepts a three-letter currency, a start date, and an optional end date, then loads the interval average from CBR using OkHttp. When the end date is omitted, the interval runs through yesterday. The screen can also show the currently effective official rate. Dates use YYYY-MM-DD. The defaults are USD and three months through yesterday. Normalized rates and downloaded coverage are persisted in a Room database; historical cache coverage has the same semantics as the CLI's SQLite cache. Date fields support both ISO text entry and a calendar picker. The last successful inputs and result persist between launches, allowing the app to reopen directly on the previous result and refresh it with one tap. Android saved state also preserves in-progress UI state across activity or process recreation. The Android UI follows the device language and includes complete English and Russian resources, localized result dates and numbers, and pluralized rate counts.

Open the repository root in Android Studio, or build from a terminal with:

./gradlew test assembleDebug

With an emulator or device connected, run the Room and Compose instrumentation tests with:

./gradlew connectedDebugAndroidTest

Continuous integration

The GitHub Actions workflow runs the CLI tests with JDK 25, builds and smoke-tests the GraalVM native executable in English and Russian, and runs the Android unit tests plus debug and optimized release builds with JDK 21. Successful runs publish the Linux native executable, debug APK, and unsigned release AAB as workflow artifacts. Device and emulator instrumentation tests remain part of the local verification command shown above.

The debug APK is written to android-app/build/outputs/apk/debug/android-app-debug.apk. The app compiles and targets Android 16/API 36, uses Build Tools 36.0.0 and Java 21, and retains Android 8/API 26 as its minimum supported version.

Android release bundle

Build an optimized, resource-shrunk Android App Bundle with JDK 21:

./gradlew :android-app:bundleRelease

Without signing variables this produces an unsigned bundle for verification at android-app/build/outputs/bundle/release/android-app-release.aab. CI builds and publishes this unsigned bundle as an artifact.

For a distributable bundle, first create and securely back up an upload keystore using Android Studio's Build > Generate Signed Bundle/APK flow. Then provide all four signing values as environment variables:

export ROUBLE_RATE_KEYSTORE=/secure/path/rouble-rate-upload.jks
export ROUBLE_RATE_STORE_PASSWORD='...'
export ROUBLE_RATE_KEY_ALIAS='rouble-rate-upload'
export ROUBLE_RATE_KEY_PASSWORD='...'
./gradlew :android-app:bundleRelease

The build fails when only some signing variables are present, preventing an accidentally misconfigured release. Keystores and keystore.properties are ignored by Git and must never be committed. For Google Play distribution, use this as the upload key and enroll the application in Play App Signing.

Modules

  • rate-core is a standalone Java 21, JDK-only library containing the data model, calculations, use cases, and the ExchangeRateSource and ExchangeRateStore contracts. It is intended to be shared with Android.
  • rate-cbr is a Java 21 library containing the shared CBR XML parser and its raw transport interface.
  • rate-cli contains Picocli presentation, Java HTTP, the SQLite store, and GraalVM native-image configuration.
  • android-app contains Kotlin/Compose UI, OkHttp transport, and Room storage.

About

Java command-line program that downloads official exchange-rate history from the Bank of Russia and calculates arithmetic averages for requested day, week, month or year periods

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages