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
Android library which makes it easy to handle the different obstacles while calling an API (Web Service) in Android App.

API Calling Flow API Calling Flow is a Android library which can help you to simplify handling different conditions while calling an API (Web Service)

Rohit Surwase 19 Nov 9, 2021
Android Utilities Library build in kotlin Provide user 100 of pre defined method to create advanced native android app.

Android Utilities Library build in kotlin Provide user 100 of pre defined method to create advanced native android app.

Shahid Iqbal 4 Nov 29, 2022
A robust native library loader for Android.

ReLinker A robust native library loader for Android. More information can be found in our blog post Min SDK: 9 JavaDoc Overview The Android PackageMan

Keepsafe 2.9k Dec 27, 2022
UPnP/DLNA library for Java and Android

Cling EOL: This project is no longer actively maintained, code may be outdated. If you are interested in maintaining and developing this project, comm

4th Line 1.6k Jan 4, 2023
:iphone: [Android Library] Get device information in a super easy way.

EasyDeviceInfo Android library to get device information in a super easy way. The library is built for simplicity and approachability. It not only eli

Nishant Srivastava 1.7k Dec 22, 2022
Android library for viewing, editing and sharing in app databases.

DbInspector DbInspector provides a simple way to view the contents of the in-app database for debugging purposes. There is no need to pull the databas

Infinum 924 Jan 4, 2023
Android Market In-app Billing Library

Update In-app Billing v2 API is deprecated and will be shut down in January 2015. This library was developed for v2 a long time ago. If your app is st

Robot Media 533 Nov 25, 2022
An Android library allowing images to exhibit a parallax effect that reacts to the device's tilt

Motion An Android library allowing images to exhibit a parallax effect. By replacing static pictures and backgrounds with a fluid images that reacts t

Nathan VanBenschoten 781 Nov 11, 2022
Android library to easily serialize and cache your objects to disk using key/value pairs.

Deprecated This project is no longer maintained. No new issues or pull requests will be accepted. You can still use the source or fork the project to

Anup Cowkur 667 Dec 22, 2022
Form Validator Library for Android

Android-Validator Form Validator Library for Android [](https://flattr.com/submit/auto?user_id=throrin19&url=https://github.com/throrin19/Android-Vali

Benjamin Besse 449 Dec 17, 2022
Very easy to use wrapper library for Android SharePreferences

Treasure English document Treasure是一个Android平台上基于SharePreferences的偏好存储库,只需要定义接口,无需编写实现,默认支持Serializable和Parcelable。运行时0反射,不仅使用方便而且性能和原生写法几乎无差别。 使用方法 1

星一 507 Nov 12, 2022
Error handling library for Android and Java

ErrorHandler Error handling library for Android and Java Encapsulate error handling logic into objects that adhere to configurable defaults. Then pass

null 237 Dec 29, 2022
Small Android library to help you incorporate MVP, Passive View and Presentation Model patterns in your app

DroidMVP About DroidMVP is a small Android library to help you incorporate the MVP pattern along with Passive View and Presentation Model (yes, those

Andrzej Chmielewski 225 Nov 29, 2022
A simple Android utils library to write any type of data into cache files and read them later.

CacheUtilsLibrary This is a simple Android utils library to write any type of data into cache files and then read them later, using Gson to serialize

Wesley Lin 134 Nov 25, 2022
Android library that regroup bunch of dateTime utilities

DateTimeUtils This library is a package of functions that let you manipulate objects and or java date string. it combine the most common functions use

Thunder413 98 Nov 16, 2022
Slinger - deep linking library for Android

Slinger - deep linking library for Android Slinger is a small Android library for handling custom Uri which uses regular expression to catch and route

Allegro Tech 27 Dec 8, 2022
A simple and easy to use stopwatch and timer library for android

TimeIt Now with Timer support! A simple and easy to use stopwatch and timer library for android Introduction A stopwatch can be a very important widge

Yashovardhan Dhanania 35 Dec 10, 2022
Trail is a simple logging system for Java and Android. Create logs using the same API and the library will detect automatically in which platform the code is running.

Trail Trail is a simple logging system for Java and Android. Create logs using the same API and the library will detect automatically in which platfor

Mauricio Togneri 13 Aug 29, 2022
UI form validation library for Android

Android Saripaar v2 சரிபார் - sari-paar (Tamil for "to check", "verify" or "validate") Android Saripaar is a simple, feature-rich and powerful rule-ba

Ragunath Jawahar 3.2k Dec 29, 2022