Joda-Time library with Android specialization

Overview

joda-time-android

This library is a version of Joda-Time built with Android in mind.

Why Joda-Time?

Android has built-in date and time handling - why bother with a library? If you've worked with Java's Date and Calendar classes you can probably answer this question yourself, but if not, check out Joda-Time's list of benefits.

For Android developers Joda-Time solves one critical problem: stale timezone data. Built-in timezone data is only updated when the OS is updated, and we all know how often that happens. Countries modify their timezones all the time; being able to update your own tz data keeps your app up-to-date and accurate.

Why This Library?

I know what you are thinking: Joda-Time is a great library and it's just a single JAR, so why make things more complex by wrapping it in an Android library?

There is a particular problem with the JAR setup on Android: due to its usage of ClassLoader.getResourceAsStream(), it greatly inflates its memory footprint on apps. (For more details, see this blog post.) This library avoids the problem for Android by loading from resources instead of a JAR.

This library also has extra utilities designed for Android. For example, see DateUtils, a port of Android's DateUtils.

Usage

Add the following dependency to build.gradle:

dependencies {
    implementation 'net.danlew:android.joda:2.10.9.1'
}

Multi-Process Apps

Due to using App Startup, joda-time-android will not automatically initialize in non-main processes.

If you would like to automatically run App Startup in other processes, add this to your manifest:

<provider
    android:name="androidx.startup.InitializationProvider"
    android:authorities="${applicationId}.androidx-startup"
    android:exported="false"
    android:process="[your-process-name-here]"
    tools:node="merge" />

Alternatively, you can call AppInitializer directly to initialize just joda-time-android:

AppInitializer.getInstance(this).initializeComponent(JodaTimeInitializer::class.java)

Troubleshooting

Q: My build fails with an error about a duplicate file

Duplicate files copied in APK META-INF/LICENSE.txt

or

Duplicate files copied in APK META-INF/NOTICE.txt

A: We can safely exclude those files from our build. You need to specify these two excludes in your build.gradle file and you will be good to go:

android {
    ...
    packagingOptions {
        exclude 'META-INF/LICENSE.txt'
        exclude 'META-INF/NOTICE.txt'
    }
}

or

B: We can safely choose to add those files to our build. You need to specify these two merges in your build.gradle file and you will be good to go:

android {
    ...
    packagingOptions {
        merge '**/LICENSE.txt'
        merge '**/NOTICE.txt'
    }
}
Comments
  • can't find referenced class org.joda.time.tz.ZoneInfoCompiler

    can't find referenced class org.joda.time.tz.ZoneInfoCompiler

    I can't generate a apk with proguard active, I always get the following warning:

    Warning:org.joda.time.tz.DateTimeZoneBuilder$PrecalculatedZone: can't find referenced class org.joda.time.tz.ZoneInfoCompiler

    I know I could add -dontwarn org.joda.time.tz.**, but then the app crashes when I call JodaTimeAndroid.init(this);

    @Override protected void onCreate(Bundle bundle) { super.onCreate(bundle); setContentView(R.layout.activity_main); JodaTimeAndroid.init(this); }

    I'm using Android Studio

    the exception I get when I use -dontwarn:

    02-22 12:57:16.237 6971-6971/? E/JodaTimeAndroid﹕ Failed to retrieve identifier: type=class net.danlew.android.joda.R$raw name=__tzdata_zoneinfomap java.lang.NoSuchFieldException: __tzdata_zoneinfomap at java.lang.Class.getField(Class.java:1048) at net.danlew.android.joda.ResUtils.getIdentifier(ResUtils.java:105) at net.danlew.android.joda.ResourceZoneInfoProvider.openResource(ResourceZoneInfoProvider.java:114) at net.danlew.android.joda.ResourceZoneInfoProvider.(ResourceZoneInfoProvider.java:39) at net.danlew.android.joda.JodaTimeAndroid.init(JodaTimeAndroid.java:39) at com.newApp.MainActivity.onCreate(MainActivity.java:158) at android.app.Activity.performCreate(Activity.java:5933) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2251) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360) at android.app.ActivityThread.access$800(ActivityThread.java:144) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5221) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694) 02-22 12:57:16.239 6971-6971/? E/AndroidRuntime﹕ FATAL EXCEPTION: main Process: com.newApp, PID: 6971 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.newApp/com.newApp.MainActivity}: java.lang.RuntimeException: Could not read ZoneInfoMap at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2298) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360) at android.app.ActivityThread.access$800(ActivityThread.java:144) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5221) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694) Caused by: java.lang.RuntimeException: Could not read ZoneInfoMap at net.danlew.android.joda.JodaTimeAndroid.init(JodaTimeAndroid.java:42) at com.newApp.MainActivity.onCreate(MainActivity.java:158) at android.app.Activity.performCreate(Activity.java:5933) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2251)             at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)             at android.app.ActivityThread.access$800(ActivityThread.java:144)             at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)             at android.os.Handler.dispatchMessage(Handler.java:102)             at android.os.Looper.loop(Looper.java:135)             at android.app.ActivityThread.main(ActivityThread.java:5221)             at java.lang.reflect.Method.invoke(Native Method)             at java.lang.reflect.Method.invoke(Method.java:372)             at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)             at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)

    opened by samuelba 27
  • new DateTime() uses UTC instead of current system time zone

    new DateTime() uses UTC instead of current system time zone

    I compile this lib with gradle and initialise it in Application onCreate(). I am in time zone UTC+2, and this is what my phone indicates. When I call new DateTime() I always get time in UTC, what is wrong according to documentation.

    opened by kolczak 25
  • Could not read ZoneInfoMap. You are probably using Proguard wrong.

    Could not read ZoneInfoMap. You are probably using Proguard wrong.

    Hi,

    This is the stacktrace without any proguard rules

    Caused by: java.lang.RuntimeException: Could not read ZoneInfoMap. You are probably using Proguard wrong.
                                                           at net.danlew.android.joda.a.a(JodaTimeAndroid.java:42)
    
    Failed to retrieve identifier: type=class net.danlew.android.joda.b$a name=joda_zoneinfomap
                                                        java.lang.NoSuchFieldException: joda_zoneinfomap
                                                            at java.lang.Class.getField(Class.java:891)
                                                            at net.danlew.android.joda.c.a(ResUtils.java:105)
                                                            at net.danlew.android.joda.d.a(ResourceZoneInfoProvider.java:113)
                                                            at net.danlew.android.joda.d.<init>(ResourceZoneInfoProvider.java:38)
                                                            at net.danlew.android.joda.a.a(JodaTimeAndroid.java:39)
    

    Using these rules solve the problem but I wonder what do you recommend

    -dontwarn org.joda.convert.**
    -dontwarn org.joda.time.**
    -keep class org.joda.time.** { *; }
    -keep interface org.joda.time.** { *; }
    -keep class net.danlew.** { *; }
    
    opened by alexhorsa 13
  • ZoneInfoMap not found for unit tests, but only for v2.9.4/2.9.4.1

    ZoneInfoMap not found for unit tests, but only for v2.9.4/2.9.4.1

    This is very similar to #17, #37, and #118 but with some differences that I couldn't resolve using the comments on those issues.

    When I run JVM unit tests on my Android project, I'm seeing this error:

    java.io.IOException: Resource not found: "org/joda/time/tz/data/ZoneInfoMap" ClassLoader: sun.misc.Launcher$AppClassLoader@6d06d69c

    This happens even though I'm using these dependency settings:

    compile "net.danlew:android.joda:${jodaTimeAndroidVersion}" testCompile "joda-time:joda-time:${jodaTimeVersion}"

    The really strange thing is that this is only happening when I use the latest versions of the app

    | joda-time-android version | joda-time version | issue present? | | --- | --- | --- | | 2.9.3 | 2.9.3 | no | | 2.9.3.1 | 2.9.3 | no | | 2.9.4 | 2.9.4 | yes | | 2.9.4.1 | 2.9.4 | yes |

    Any ideas on why this would be happening?

    opened by vaughandroid 13
  • JodaTimeAndroid.init(this); crashes with FileNotFoundException for res/raw/joda_time_android_tzdata_zoneinfomap

    JodaTimeAndroid.init(this); crashes with FileNotFoundException for res/raw/joda_time_android_tzdata_zoneinfomap

    I'm using joda-time-android library in a project, but I'm getting quite a number of daily crashes of JodaTimeAndroid.init(this); call which is located in Applicaion overrride class in onCreate(*) method. Here's a stack trace:

    Caused by: java.io.FileNotFoundException: res/raw/joda_time_android_tzdata_zoneinfomap
    at android.content.res.AssetManager.openNonAssetNative(Native Method)
    at android.content.res.AssetManager.openNonAsset(AssetManager.java:446)
    at android.content.res.Resources.openRawResource(Resources.java:1158)
    ... 16 more
    android.content.res.Resources$NotFoundException: File res/raw/joda_time_android_tzdata_zoneinfomap from drawable resource ID #0x7f0701f7
    at android.content.res.Resources.openRawResource(Resources.java:1161)
    at android.content.res.Resources.openRawResource(Resources.java:1132)
    at a.a.a.a.e.a(SourceFile:120)
    at a.a.a.a.e.<init>(SourceFile:39)
    at a.a.a.a.a.a(SourceFile:39)
    at com.example.main.AppOverride.onCreate(SourceFile:46)
    

    It's very weird to me because majority of devices work perfectly fine with it, however this issue also occurs on some quite popular devices like Nexus5/LG G3/several Samsung models etc

    opened by aviadmini 13
  • Unit test error

    Unit test error

    I followed the directions on this page: http://tools.android.com/tech-docs/unit-testing-support

    I created a test class, compiled it but I ran into this: Resource not found: "org/joda/time/tz/data/ZoneInfoMap" ClassLoader: sun.misc.Launcher$AppClassLoader@5bdf59bd

    I copied everything to a simple Java project (switched to IntelliJ) and my unit tests ran just fine.

    Gradle info compile 'net.danlew:android.joda:2.7.1' testCompile 'junit:junit:4.12'

    opened by appmath 13
  • Comparison to ThreeTenABP

    Comparison to ThreeTenABP

    I am sorry to ask you this bluntly, but how does your solution compares to: https://github.com/JakeWharton/ThreeTenABP

    I am evaluating a good way to implement JSR-310 on old devices and I can't figure how you two are different and which one to choose.

    opened by feinstein 10
  • Wrong translation for russian text

    Wrong translation for russian text

    Affected file: https://github.com/dlew/joda-time-android/blob/master/library/src/main/res/values-ru/strings.xml

    For quantity="one", number "1" is hardcoded. This is wrong, because for example number 41 matches quantity="one" in Russian language, so instead of "41 minute ago" we get "1 minute ago" (I used English text just for example)

    opened by deinlandel 10
  • Usage in unit testing

    Usage in unit testing

    When unit testing the Android app (junit.framework.TestCase or Junit 4 tests from a pure submodule) joda-time-android cannot be used as it requires a context as part of the JodaTimeAndroid.initialization.

    The alternative is to obviously just use joda-time for submodules and converting TestCases to AndroidTestCases (in the process getting hold of a context for initialization).

    In you experience have you had to deal with a similar case and if so did you choose an alternative nicer approach for unit testing? Conceptually it would be nice to have the exact same JodaTime library used for both testing and production, but is this just a limitation that can't be overcome?

    Cheers

    opened by kaushikgopal 10
  • Scope ProGuard rules to library

    Scope ProGuard rules to library

    ProGuard rules are really easy to add from different libraries, but they are hard to exclude from a subset of libraries. I'd suggest scope all rules under the Joda namespace, to avoid collisions with other libraries / main packages.

    We are stuck with version 2.10.6 because of the insertion of these rules. When keeping the names of everything that implements Serializable (directly or indirectly), a good portion of the code (especially when using Kotlin / Kotlin Serialization) is not obfuscated, despite it being able to run correctly without the rules. Scoping the rules to the library only, not only makes sense from a packaging perspective, but also allows for better control over what need Serialization and what doesn't.

    I've also found out that we do not need the name of the classes to be kept, Joda works correctly without them, because serialization appears to be used only in live environment where the class is renamed but constant. Better testing might be needed here, but I can't find a point where it differs. If we want to keep the class name as well, I'd suggest we scope it under the Joda namespace too.

    This leads to both more obfuscation and lower bundle size. Let me know if you need more details on this.

    opened by TheNodi 9
  • Wrong LocalTime while converting from one timezone to another

    Wrong LocalTime while converting from one timezone to another

    I used sample application and have just changed sampleLocalDate method:

    `private void sampleLocalDate() {
            List<String> text = new ArrayList<String>();
            LocalDate now = LocalDate.now();
            text.add("Now: " + now);
            long startDayMillis = now.toDateTimeAtStartOfDay().getMillis();
            text.add("LocalDate in millis: " + startDayMillis);
    
            long startDayMillisInUTC = now.toDateTimeAtStartOfDay().withZone(DateTimeZone.UTC).getMillis();
            text.add("startDayMillisInUTC: " + startDayMillisInUTC);
    
            text.add("LocalDate after converting: " + new LocalDate(startDayMillis));
            text.add("Now + 2 days: " + now.plusDays(2));
            text.add("Now + 3 months: " + now.plusMonths(3));
    
            text.add("----------------------------------------------");
    
            LocalTime time = new LocalTime(DateTimeZone.UTC);
            text.add("LocalTime: " + time);
            long timeNowMillis = time.getMillisOfDay();
            text.add("LocalTime in millis - timeNowMillis: " + timeNowMillis);
            long millis = time.getMillisOfDay();
            LocalTime localTime = new LocalTime(millis, DateTimeZone.UTC);
            text.add("LocalTime, getMillisOfDay: " + millis + "; local time (UTC) - " + localTime);
            TimeZone timeZone = TimeZone.getDefault();
            text.add("Timezone: rawOffset: " + timeZone.getRawOffset()/(60*60*1000) + "; timezone - " + timeZone.toString());
            text.add("LocalTime, local time (device timezone) - "
                    + new LocalTime(millis, DateTimeZone.getDefault())
    //                + new DateTime(millis, DateTimeZone.forTimeZone(timeZone))
            );
            text.add("difference between timeNowMillis and startDayMillis: " + new LocalTime(timeNowMillis - startDayMillis, DateTimeZone.UTC));
    
            addSample("LocalDate", text);`
    

    My idea is - I have LocalTime in UTC and save it as long in database. So, I can restore long timestamp and convert it in LocalTime in UTC. This works well. But I 'd like to convert LocalTime(UTC) to LocalTime(TimeZoneOfMyDevice). I tried converting but I had an issue - converted LocalTime differ from current time

    device-2017-11-07-184846

    What could be wrong in my case? Device: Xiaomi Redmi Note 4X, MTK

    opened by zezekalo 9
  • Unable to pull new versions using gradle

    Unable to pull new versions using gradle

    I'm trying to update to the latest version of this library and gradle doesn't find the versions specified. I have version 2.10.7.2 and I didn't manage to migrate to later version.

    Is it possible that the publishing mechanism is effected by the Jcenter deprecation?

    opened by NoaD 4
Releases(v2.12.1.1)
Owner
Daniel Lew
Daniel Lew
Asimov-time-kt - Useful time and date related functions and extensions

asimov/time Useful time and date related functions and extensions. Installation

Nicolas Bottarini 1 Jan 7, 2022
KotlinX multiplatform date/time library

kotlinx-datetime A multiplatform Kotlin library for working with date and time. See Using in your projects for the instructions how to setup a depende

Kotlin 1.6k Jan 5, 2023
Multiplatform Date and time library for Kotlin

Klock is a Date & Time library for Multiplatform Kotlin. It is designed to be as allocation-free as possible using Kotlin inline classes, to be consis

null 681 Dec 19, 2022
Additions for Kotlin's date & time library kotlinx-datetime

fluid-time Additions for Kotlin's date & time library kotlinx-datetime. kotlinx-datetime is very early stage and not as actively developed as other of

Marc Knaup 39 Nov 11, 2022
java.time Kotlin extension functions library.

Java Time Kotlin extension functions. Background Java Time became integrated to the JDK as of Java 8. It was a huge improvement over its Date predeces

Sami Eljabali 31 Mar 15, 2022
A material-styled android view that provisions picking of a date, time & recurrence option, all from a single user-interface.

SublimePicker A customizable view that provisions picking of a date, time & recurrence option, all from a single user-interface. You can also view 'Su

Vikram 2.3k Jan 4, 2023
Pick a date or time on Android in style

Material DateTime Picker - Select a time/date in style Material DateTime Picker tries to offer you the date and time pickers as shown in the Material

null 4.7k Dec 29, 2022
Estimated Time of Arrival Bar

Estimated Time of Arrival Bar

Tek 1 Mar 12, 2022
Asimov-flagz-kt - Feature flags library based on Togglz library

Asimov Flagz Feature flags library based on Togglz library. Installation Gradle

Nicolas Bottarini 1 Jan 8, 2022
Android Week View is an android library to display calendars (week view or day view) within the app. It supports custom styling.

Android Week View Android Week View is an android library to display calendars (week view or day view) within the app. It supports custom styling. Fea

Raquib-ul Alam (Kanak) 3.4k Jan 3, 2023
Android library for better Picker DialogFragments

DialogFragments modeled after the AOSP Clock and Calendar apps to improve UX for picking time, date, numbers, and other things.

Code-Troopers 2.7k Dec 29, 2022
An android library which provides a compact calendar view much like the one used in google calenders.

CompactCalendarView CompactCalendarView is a simple calendar view which provides scrolling between months. It's based on Java's Date and Calendar clas

SundeepK 1.5k Jan 7, 2023
android library dialog month picker

RackMonthPicker android library dialog month picker Download Download via Maven: Add the JitPack repository to your build file <repositories> <rep

Kristiawan Adi L 41 Aug 13, 2022
CustomizableCalendar is a library that allows you to create your calendar, customizing UI and behaviour

CustomizableCalendar This library allows you to create a completely customizable calendar. You can use CustomizableCalendar to create your calendar, c

MOLO17 216 Dec 6, 2022
A simple library which gives you custom design CalendarView with dialog functionality and event handlers.

CalendarView A simple library which gives you custom design CalendarView with dialog functionality and event handlers. 1: CalendarView Demo Screen 1.1

Shahzad Afridi (Opriday) 49 Oct 28, 2022
A Kotlin Multiplatform library for working with dates and times

Island Time A Kotlin Multiplatform library for working with dates and times, heavily inspired by the java.time library. Features: A full set of date-t

Erik Christensen 71 Dec 28, 2022
Kmpcalendar - A calendar library and views written for kotlin multiplatform

KMPCalendarView Minimal Kotlin Multiplatform project with SwiftUI, Jetpack Compo

Anmol Verma 2 Oct 7, 2022
A Jetpack Compose library for handling calendar component rendering.

Compose Calendar Compose Calendar is a composable handling all complexity of rendering calendar component and date selection. Due to flexibility provi

Bogusz Pawłowski 181 Dec 22, 2022
📅 Minimal Calendar - This calendar library is built with jetpack compose. Easy, simple, and minimal.

?? Minimal Calendar This calendar library is built with jetpack compose. Easy, simple, and minimal. Latest version The stable version of the library i

Minjae Kim 16 Sep 14, 2022