### LocalDateTime Usage Example Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/types.md Shows how to get the current LocalDateTime, create a specific instance, and convert it to a ZonedDateTime. ```java LocalDateTime now = LocalDateTime.now(); LocalDateTime eventTime = LocalDateTime.of(2024, 12, 25, 14, 30); ZonedDateTime withZone = eventTime.atZone(ZoneId.of("America/New_York")); ``` -------------------------------- ### OffsetDateTime Usage Example Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/types.md Shows how to create an OffsetDateTime with the current local date-time and a specified offset, and convert it to an Instant. ```java OffsetDateTime dateTime = OffsetDateTime.of( LocalDateTime.now(), ZoneOffset.of("+02:00") ); Instant asInstant = dateTime.toInstant(); ``` -------------------------------- ### Usage Example for Month and DayOfWeek Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/types.md Demonstrates how to get the current day of the week and month from a LocalDate, and how to display the month's full name in English. Requires importing `java.time.LocalDate`, `java.time.DayOfWeek`, `java.time.Month`, `java.time.format.TextStyle`, and `java.util.Locale`. ```java LocalDate today = LocalDate.now(); DayOfWeek dayOfWeek = today.getDayOfWeek(); Month month = today.getMonth(); System.out.println(month.getDisplayName(TextStyle.FULL, Locale.ENGLISH)); // Output: "January", "February", etc. ``` -------------------------------- ### Period Usage Example Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/types.md Demonstrates creating Period objects using `between` and `ofDays`/`ofMonths`, and accessing its components. ```java LocalDate birthday = LocalDate.of(1990, 5, 15); LocalDate today = LocalDate.now(); Period age = Period.between(birthday, today); System.out.println("Age: " + age.getYears() + " years"); // Create periods Period twoDays = Period.ofDays(2); Period oneMonth = Period.ofMonths(1); ``` -------------------------------- ### ZoneId Usage Example Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/types.md Shows how to create a ZoneId for New York and use it to create a ZonedDateTime. Also demonstrates retrieving all available zone IDs. ```java ZoneId zone = ZoneId.of("America/New_York"); ZonedDateTime noonInNY = LocalDateTime.of(2024, 1, 1, 12, 0) .atZone(zone); // Get all zones Set allZones = ZoneId.getAvailableZoneIds(); ``` -------------------------------- ### Common Zone IDs Examples Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/types.md Illustrates creating ZoneId objects for various geographical regions and the system's default timezone. ```java ZoneId.of("UTC") // UTC/GMT ZoneId.of("America/New_York") // Eastern Time ZoneId.of("America/Chicago") // Central Time ZoneId.of("America/Denver") // Mountain Time ZoneId.of("America/Los_Angeles") // Pacific Time ZoneId.of("America/Anchorage") // Alaska Time ZoneId.of("Europe/London") // GMT/BST ZoneId.of("Europe/Paris") // CET/CEST ZoneId.of("Asia/Tokyo") // JST ZoneId.of("Australia/Sydney") // AEDT/AEST ZoneId.of("Asia/Hong_Kong") // HKT ZoneId.of("Asia/Dubai") // GST ZoneId.systemDefault() // Device's timezone ``` -------------------------------- ### Duration Usage Example Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/types.md Illustrates calculating the duration between two Instants and creating Duration objects for specific time spans. ```java Instant start = Instant.now(); // ... do something ... Instant end = Instant.now(); Duration elapsed = Duration.between(start, end); System.out.println("Elapsed: " + elapsed.toMillis() + " ms"); // Create durations Duration timeout = Duration.ofSeconds(30); Duration delay = Duration.ofMinutes(5); ``` -------------------------------- ### ZonedDateTime Usage Example Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/types.md Demonstrates obtaining the current time in a specific timezone, converting between timezones, and creating from an Instant. ```java // Current time with timezone ZonedDateTime now = ZonedDateTime.now(); // Specific timezone ZonedDateTime nyTime = ZonedDateTime.now(ZoneId.of("America/New_York")); // Convert between timezones ZonedDateTime tokyo = nyTime.withZoneSameInstant(ZoneId.of("Asia/Tokyo")); // From instant ZonedDateTime utcTime = ZonedDateTime.ofInstant(Instant.now(), ZoneId.of("UTC")); ``` -------------------------------- ### Convert Between LocalDate, LocalDateTime, ZonedDateTime, and Instant Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/api-reference/JSR310-Overview.md Provides examples for converting between different date and time types including LocalDate, LocalDateTime, ZonedDateTime, and Instant. ```java // LocalDate to LocalDateTime LocalDate date = LocalDate.now(); LocalDateTime start = date.atStartOfDay(); // 00:00:00 LocalDateTime with_time = date.atTime(14, 30); // 14:30:00 // LocalDateTime to ZonedDateTime LocalDateTime local = LocalDateTime.now(); ZonedDateTime zoned = local.atZone(ZoneId.systemDefault()); // Instant to LocalDate Instant moment = Instant.now(); LocalDate date = moment.atZone(ZoneId.systemDefault()).toLocalDate(); // ZonedDateTime back to Instant ZonedDateTime zdt = ZonedDateTime.now(); Instant back = zdt.toInstant(); ``` -------------------------------- ### Examples of Valid Custom Asset Paths Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/configuration.md Demonstrates valid ways to specify custom asset paths for the timezone database. Paths can be in subdirectories or use different filenames, as long as they are relative to the `assets/` directory. ```java // Default location AndroidThreeTen.init(context); // Custom subdirectory AndroidThreeTen.init(context, "tzdata/TZDB.dat"); // Deeply nested AndroidThreeTen.init(context, "lib/tz/prod/TZDB.dat"); // Different filename AndroidThreeTen.init(context, "zone-rules.dat"); ``` -------------------------------- ### Timezone Awareness Example Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/api-reference/JSR310-Overview.md Shows how to work with timezones using `Instant` and `ZonedDateTime`. `Instant` represents a UTC point in time, while `ZonedDateTime` includes timezone information. ```java // Instant: always UTC Instant utcNow = Instant.now(); // With timezone ZonedDateTime nyTime = Instant.now().atZone(ZoneId.of("America/New_York")); ZonedDateTime tokyoTime = Instant.now().atZone(ZoneId.of("Asia/Tokyo")); // Different zones, same instant nyTime.toInstant().equals(tokyoTime.toInstant()); // true ``` -------------------------------- ### ZoneOffset Usage Example Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/types.md Demonstrates creating ZoneOffset objects for specific offsets like India Standard Time and UTC, and using them to create an OffsetDateTime. ```java ZoneOffset offset = ZoneOffset.of("+05:30"); // India Standard Time ZoneOffset utc = ZoneOffset.UTC; ZoneOffset eastern = ZoneOffset.of("-05:00"); OffsetDateTime odt = OffsetDateTime.of( 2024, 1, 1, 12, 0, 0, 0, ZoneOffset.of("+01:00") ); ``` -------------------------------- ### Factory Methods: Current Time/Date Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/api-reference/JSR310-Overview.md Demonstrates how to get the current moment, date, time, or date-time with or without a time zone. ```APIDOC ## Factory Methods: Current Time/Date ### Description Get the current moment, date, time, or date-time with or without a time zone. ### Code Examples ```java Instant.now(); // Current moment LocalDate.now(); // Today LocalTime.now(); // Current time LocalDateTime.now(); // Current date and time ZonedDateTime.now(); // Current date/time with zone ZonedDateTime.now(ZoneId.of("America/New_York")); // Now in specific zone ``` ``` -------------------------------- ### Initialize ThreeTenABP in Android Tests Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/configuration.md Initialize the library in your Android instrumented tests using AndroidThreeTen.init(). This setup is required before accessing timezone data. ```java @RunWith(AndroidJUnit4.class) public class DateTimeTest { private Context context; @Before public void setUp() { context = InstrumentationRegistry.getInstrumentation().getContext(); AndroidThreeTen.init(context); } @Test public void testZoneAccess() { ZoneId zone = ZoneId.of("UTC"); assertNotNull(zone); } } ``` -------------------------------- ### Natural Date Arithmetic Example Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/api-reference/JSR310-Overview.md Demonstrates natural date arithmetic using `plus` and `minus` methods for units like months, years, and days. This handles month boundaries and leap years automatically. ```java LocalDate today = LocalDate.now(); // Natural date arithmetic LocalDate nextMonth = today.plusMonths(1); LocalDate lastYear = today.minusYears(1); LocalDate nextWeekday = today.plusDays(1); // Handles month boundaries automatically LocalDate jan31 = LocalDate.of(2024, 1, 31); LocalDate feb29 = jan31.plusMonths(1); // 2024-02-29 (leap year) ``` -------------------------------- ### Get Available Timezones and Create Zoned DateTimes Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/api-reference/JSR310-Overview.md Demonstrates how to retrieve all available time zone IDs and create zoned date-time objects for specific zones. ```java Set allZones = ZoneId.getAvailableZoneIds(); ZoneId ny = ZoneId.of("America/New_York"); ZoneId tokyo = ZoneId.of("Asia/Tokyo"); ZoneId system = ZoneId.systemDefault(); LocalDateTime local = LocalDateTime.of(2024, 1, 15, 14, 30); ZonedDateTime ny_time = local.atZone(ny); ``` -------------------------------- ### Locale-Specific Date and Time Formatting Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/configuration.md Demonstrates how to use the device's default locale or a specific locale for formatting dates and getting month names. Ensure necessary imports are included. ```java import java.util.Locale; import org.threeten.bp.LocalDate; import org.threeten.bp.format.DateTimeFormatter; import org.threeten.bp.format.TextStyle; LocalDate date = LocalDate.now(); // Use device locale String monthName = date.getMonth().getDisplayName(TextStyle.FULL, Locale.getDefault()); // Use specific locale DateTimeFormatter formatter = DateTimeFormatter .ofPattern("EEEE, MMMM d, yyyy", Locale.ENGLISH); String formatted = date.format(formatter); ``` -------------------------------- ### Safe Multi-threaded Usage Example Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/architecture.md Demonstrates how to safely use ThreeTenABP's immutable date/time objects across multiple threads concurrently after initialization. ```java // Application.onCreate() - main thread AndroidThreeTen.init(context); // Background threads executorService.submit(() -> { // Safe: already initialized ZonedDateTime zdt = ZonedDateTime.now(); }); executorService.submit(() -> { // Safe: concurrent access LocalDate today = LocalDate.now(); }); ``` -------------------------------- ### Idempotent and Thread-Safe Initialization Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/initialization-guide.md Initialize ThreeTenABP using `AndroidThreeTen.init()` with a `Context`. The initialization is safe to call multiple times and from multiple threads; only the first call performs the actual setup. ```java // All of these are safe and have no side effects AndroidThreeTen.init(context); AndroidThreeTen.init(context); AndroidThreeTen.init(application); // Safe in multi-threaded code new Thread(() -> AndroidThreeTen.init(context)).start(); ``` -------------------------------- ### Application Initialization Flow Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/overview.md Illustrates the sequence of calls during application startup for initializing the ThreeTen Android Backport library. Ensure this is called in `Application.onCreate()`. ```text Application.onCreate() → AndroidThreeTen.init(Context) → AssetsZoneRulesInitializer created with asset path → ZoneRulesInitializer.setInitializer() registers the custom initializer → On first zone query, timezone data loaded from assets/org/threeten/bp/TZDB.dat → TzdbZoneRulesProvider parses TZDB data and registers available zones ``` -------------------------------- ### Initialize ThreeTenABP with Assets Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/api-reference/AssetsZoneRulesInitializer.md Call this during application startup to initialize the ThreeTenABP library, specifying the path to the TZDB data file within your application's assets. ```java AndroidThreeTen.init(context, "org/threeten/bp/TZDB.dat"); ``` -------------------------------- ### ProGuard/R8 Keep Rule Example Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/api-reference/AssetsZoneRulesInitializer.md This is an example of a ProGuard/R8 keep rule. It is generally not necessary for this class unless custom rules reference internal classes. ```proguard -keep class com.jakewharton.threetenabp.AssetsZoneRulesInitializer ``` -------------------------------- ### Get Available Time Zone IDs Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/initialization-guide.md Use `ZoneId.of()` to get specific time zones or `ZoneId.getAvailableZoneIds()` to retrieve all available IDs. This is useful for understanding the scope of supported time zones. ```java ZoneId.of("UTC") ZoneId.of("America/New_York") ZoneId.of("America/Los_Angeles") ZoneId.of("America/Chicago") ZoneId.of("Europe/London") ZoneId.of("Europe/Paris") ZoneId.of("Asia/Tokyo") ZoneId.of("Asia/Hong_Kong") ZoneId.of("Australia/Sydney") ``` ```java Set allZones = ZoneId.getAvailableZoneIds(); for (String zone : allZones) { System.out.println(zone); } ``` -------------------------------- ### Initialize with Activity Context Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/api-reference/AndroidThreeTen.md Initialize the library using an Activity's context. While functional, it's generally recommended to initialize in `Application.onCreate()` to ensure availability across all components. ```java public class MyActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); AndroidThreeTen.init(this); // Now JSR-310 APIs are available } } ``` -------------------------------- ### Initialize with Application Context Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/api-reference/AndroidThreeTen.md Initializes the ThreeTen Android Backport library using the default timezone database asset path with an Application context. This is the recommended way to initialize the library. ```APIDOC ## init(Application application) ### Description Initializes the ThreeTen Android Backport library using the default timezone database asset path. ### Method ```java public static void init(Application application) ``` ### Parameters #### Path Parameters - **application** (`android.app.Application`) - Required - The application instance, used to access Android assets ### Example Usage: ```java public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); AndroidThreeTen.init(this); } } ``` ### Notes: - Idempotent: calling `init()` multiple times is safe; the timezone database is only loaded once - Non-blocking: timezone data is loaded lazily on first use - Thread-safe: uses `AtomicBoolean` internally to ensure single initialization ``` -------------------------------- ### Wrap Initialization in Application.onCreate() Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/errors.md Initialize the ThreeTenABP library within your Application's onCreate() method and catch potential initialization errors. ```java public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); try { AndroidThreeTen.init(this); } catch (ExceptionInInitializerError e) { Log.wtf("ThreeTen", "Failed to initialize timezone database", e); // Handle gracefully or crash with clear error message } } } ``` -------------------------------- ### Initialize ThreeTenABP with Custom Asset Path Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/configuration.md Initializes the ThreeTen Android Backport library with a custom path to the timezone database asset file. The path must be relative to the `assets/` directory and should not include a leading slash or the `assets/` prefix. ```java AndroidThreeTen.init(context, "custom/path/tzdb.dat"); ``` -------------------------------- ### Date/Time Type Usage Examples Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/api-reference/JSR310-Overview.md Illustrates how to use different JSR-310 types for various date and time concepts, emphasizing the separation of concerns. ```java // Event starts at a specific local time LocalDateTime meetingTime = LocalDateTime.of(2024, 1, 15, 14, 30); // User's current local time (with timezone) ZonedDateTime nowLocal = ZonedDateTime.now(); // Record in database or API (fixed point in UTC) Instant eventUTC = meetingTime.atZone(ZoneId.of("America/New_York")).toInstant(); ``` -------------------------------- ### Initialization from Non-Application Classes Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/initialization-guide.md If direct initialization from `Application.onCreate()` is not feasible, you can initialize the library from any component that has access to a `Context`, such as an Activity, Service, or ContentProvider. ```java // From an Activity @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); AndroidThreeTen.init(this); } ``` ```java // From a Service @Override public int onStartCommand(Intent intent, int flags, int startId) { AndroidThreeTen.init(this); return START_STICKY; } ``` ```java // From a ContentProvider @Override public boolean onCreate() { AndroidThreeTen.init(getContext()); return true; } ``` -------------------------------- ### Error Handling for Initialization Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/api-reference/AndroidThreeTen.md Demonstrates how to catch potential exceptions during initialization, specifically `IllegalStateException` which may be wrapped in an `ExceptionInInitializerError` if the timezone database is not found. ```java try { AndroidThreeTen.init(context); // Use JSR-310 APIs Instant now = Instant.now(); } catch (ExceptionInInitializerError e) { if (e.getCause() instanceof IllegalStateException) { Log.e("ThreeTen", "Timezone database not found", e); } } ``` -------------------------------- ### Pre-Loading Timezone Data in Application Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/configuration.md Illustrates how to pre-load the timezone database (TZDB) during application startup by calling `ZoneId.systemDefault()` in `onCreate()`. This ensures subsequent timezone operations are fast. ```java public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); AndroidThreeTen.init(this); // Force TZDB loading ZoneId.systemDefault(); // Blocks until TZDB loaded } } ``` -------------------------------- ### Create Current Time/Date Objects Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/api-reference/JSR310-Overview.md Use factory methods to get the current moment, date, time, or date-time with or without a specific time zone. ```java Instant.now(); // Current moment LocalDate.now(); // Today LocalTime.now(); // Current time LocalDateTime.now(); // Current date and time ZonedDateTime.now(); // Current date/time with zone ZonedDateTime.now(ZoneId.of("America/New_York")); // Now in specific zone ``` -------------------------------- ### Instant Factory Methods and Accessors Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/types.md Demonstrates creating and accessing an Instant, representing a moment in time. Use for timestamps, measuring elapsed time, and serialization. ```java public final class Instant implements Comparable, Serializable { // Static factory methods public static Instant now(); public static Instant ofEpochMilli(long epochMilli); public static Instant ofEpochSecond(long epochSecond); public static Instant parse(CharSequence text); // Accessors public long toEpochMilli(); public long getEpochSecond(); // Arithmetic public Instant plus(Duration duration); public Instant minus(Duration duration); public Instant plusSeconds(long secondsToAdd); public Instant minusSeconds(long secondsToSubtract); } ``` ```java Instant now = Instant.now(); Instant epoch = Instant.ofEpochMilli(0); long millis = now.toEpochMilli(); ``` -------------------------------- ### Initialize Timezone Information Source: https://github.com/jakewharton/threetenabp/blob/trunk/README.md Initialize the timezone information for the library in your Application's onCreate() method. This is a one-time setup required for the library to function correctly. ```java import com.jakewharton.threetenabp.AndroidThreeTen; @Override public void onCreate() { super.onCreate(); AndroidThreeTen.init(this); } ``` -------------------------------- ### Initialize with Custom Asset Path Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/api-reference/AndroidThreeTen.md Use this method when you need to specify a custom location for your timezone data file. This offers more flexibility but is rarely needed. ```java AndroidThreeTen.init(context, "data/missing.dat"); ``` -------------------------------- ### Immutability Example for LocalDate Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/types.md Illustrates the immutability of date/time objects. Direct modification methods like `setYear` are not available. Instead, use `with` methods to create new instances with updated values. ```java LocalDate date = LocalDate.of(2024, 1, 1); // Cannot modify: date.setYear(2025); // Compile error // Instead, create new instance LocalDate nextYear = date.withYear(2025); ``` -------------------------------- ### Initialize with Context Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/api-reference/AndroidThreeTen.md Initializes the ThreeTen Android Backport library using the default timezone database asset path with a generic Context. This method can be called from various Android components. ```APIDOC ## init(Context context) ### Description Initializes the ThreeTen Android Backport library using the default timezone database asset path. ### Method ```java public static void init(Context context) ``` ### Parameters #### Path Parameters - **context** (`android.content.Context`) - Required - A context instance with access to application assets ### Example Usage: ```java public class MyActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); AndroidThreeTen.init(this); // Now JSR-310 APIs are available } } ``` ### Notes: - Can be called from a `Service`, `BroadcastReceiver`, or other component that has a `Context` - Recommended to call from `Application.onCreate()` to ensure initialization before any other code uses date/time APIs - Safe to call multiple times ``` -------------------------------- ### Initialize with Custom Asset Path Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/api-reference/AndroidThreeTen.md Initialize the library with a custom timezone database asset path. This is useful if you've placed your TZDB file in a non-default location within your application's assets. ```java public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); // Load timezone database from custom location AndroidThreeTen.init(this, "tzdata/custom_TZDB.dat"); } } ``` -------------------------------- ### Month and DayOfWeek Enums Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/types.md Defines the Month and DayOfWeek enums, including methods for getting their integer value and localized display names. Use `Month.of(int)` and `DayOfWeek.of(int)` to create instances. ```java public enum Month { JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER; public int getValue(); public String getDisplayName(TextStyle style, Locale locale); public static Month of(int month); } public enum DayOfWeek { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY; public int getValue(); public String getDisplayName(TextStyle style, Locale locale); public static DayOfWeek of(int dayOfWeek); } ``` -------------------------------- ### LocalDateTime Factory and Conversion Methods Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/types.md Demonstrates static factory methods for creating LocalDateTime instances and methods for converting to other temporal types. ```java public final class LocalDateTime implements Comparable, Serializable { // Static factory methods public static LocalDateTime now(); public static LocalDateTime of(LocalDate date, LocalTime time); public static LocalDateTime of(int year, int month, int day, int hour, int minute); public static LocalDateTime parse(CharSequence text); // Accessors public LocalDate toLocalDate(); public LocalTime toLocalTime(); public int getYear(); public int getMonthValue(); public int getDayOfMonth(); public int getHour(); public int getMinute(); public int getSecond(); // Arithmetic public LocalDateTime plusDays(long daysToAdd); public LocalDateTime minusHours(long hoursToSubtract); public LocalDateTime withYear(int year); // Conversion public ZonedDateTime atZone(ZoneId zone); public Instant toInstant(ZoneOffset offset); } ``` -------------------------------- ### Get Current Date and Time Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/initialization-guide.md Import `org.threeten.bp.*` to access JSR-310 APIs. Use methods like `Instant.now()`, `LocalDate.now()`, `LocalTime.now()`, `LocalDateTime.now()`, and `ZonedDateTime.now()` to retrieve current date and time information. ```java import org.threeten.bp.*; // Current instant (UTC) Instant now = Instant.now(); // Current date LocalDate today = LocalDate.now(); // Current time LocalTime currentTime = LocalTime.now(); // Current date-time LocalDateTime currentDateTime = LocalDateTime.now(); // Current date-time with zone ZonedDateTime zdt = ZonedDateTime.now(); ``` -------------------------------- ### Early Application Initialization Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/configuration.md Initialize ThreeTenABP early in your application's lifecycle by calling AndroidThreeTen.init(this) in your custom Application class's onCreate() method. This ensures timezone data is available from the start. ```java public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); AndroidThreeTen.init(this); // Early initialization } } ``` -------------------------------- ### Initialize with Custom TZDB Path Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/configuration.md Initializes the ThreeTen Android Backport library with a custom Timezone Database (TZDB) file located at a specified path within the assets. Ensure the file is in the correct binary format. ```java AndroidThreeTen.init(context, "custom/path/TZDB.dat"); ``` -------------------------------- ### Initialize with Default Asset Path Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/api-reference/AndroidThreeTen.md Call this method from Application.onCreate() for the clearest intent. The library will attempt to load timezone data from the default asset path. ```java AndroidThreeTen.init(context); ``` -------------------------------- ### Examples of Invalid Custom Asset Paths Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/configuration.md Illustrates invalid formats for custom timezone database asset paths. Paths with leading slashes, redundant `assets/` prefixes, or Windows-style path separators will not work. ```java // These will NOT work: AndroidThreeTen.init(context, "/org/threeten/bp/TZDB.dat"); // Leading slash AndroidThreeTen.init(context, "assets/org/threeten/bp/TZDB.dat"); // Redundant "assets/" AndroidThreeTen.init(context, "org\threeten\bp\TZDB.dat"); // Windows path sep ``` -------------------------------- ### Basic Initialization in Application Class Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/initialization-guide.md Initialize the library once during application startup by overriding `onCreate()` in your custom `Application` class. Ensure your custom application class is declared in `AndroidManifest.xml`. ```java public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); AndroidThreeTen.init(this); } } ``` ```xml ``` -------------------------------- ### Handle Timezone Offsets Safely Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/api-reference/JSR310-Overview.md A utility function to get the current time in a user-specified timezone. It includes error handling to default to the system's default timezone if the provided zone ID is invalid. ```java public ZonedDateTime nowInUserZone(String userZoneId) { try { return Instant.now().atZone(ZoneId.of(userZoneId)); } catch (Exception e) { return Instant.now().atZone(ZoneId.systemDefault()); } } ``` -------------------------------- ### initializeProviders() Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/api-reference/AssetsZoneRulesInitializer.md This method is called by the ThreeTenBP framework to initialize timezone data providers. It loads data from the application's assets, creates a `TzdbZoneRulesProvider`, and registers it. ```APIDOC ## initializeProviders() ### Description Initializes timezone data providers by loading rules from application assets. ### Method Signature ```java protected void initializeProviders() ``` ### Behavior 1. Opens the asset file using the stored context and asset path. 2. Creates a `TzdbZoneRulesProvider` from the input stream. 3. Registers the provider with `ZoneRulesProvider.registerProvider()`. 4. Closes the input stream in a finally block. ### Throws - `IllegalStateException`: Wrapped `IOException` if the asset file is not found or cannot be opened. The message includes the asset path that was attempted (e.g., `"org/threeten/bp/TZDB.dat missing from assets"`). ### Notes - Called exactly once per application process, on first timezone access. - Non-blocking until the first timezone query is made. - The input stream is immediately closed after the `TzdbZoneRulesProvider` is constructed. - `IOException` from closing the stream is suppressed. ``` -------------------------------- ### Deferred Initialization Errors in ThreeTenABP Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/architecture.md Initialization errors, such as missing timezone assets, are detected lazily on first access, not during `init()`. This approach speeds up startup and ensures failures only occur when zones are actually used. ```java AndroidThreeTen.init(context); // Error occurs here, on first timezone access ZoneId.of("UTC"); // ExceptionInInitializerError ``` -------------------------------- ### Initialize ThreeTenABP Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/initialization-guide.md Call AndroidThreeTen.init() before using date/time APIs to avoid 'timezone database not found' errors. Ensure the call is on the main thread. ```java AndroidThreeTen.init(this); ``` -------------------------------- ### Initialize with Custom Asset Path Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/api-reference/AndroidThreeTen.md Initializes the ThreeTen Android Backport library with a custom timezone database asset path. This allows for using a timezone database file located at a different path within the assets directory. ```APIDOC ## init(Context context, String assetPath) ### Description Initializes the ThreeTen Android Backport library with a custom timezone database asset path. ### Method ```java public static void init(Context context, String assetPath) ``` ### Parameters #### Path Parameters - **context** (`android.content.Context`) - Required - A context instance with access to application assets - **assetPath** (`String`) - Required - Path to the timezone database asset relative to the assets directory (e.g., `org/threeten/bp/TZDB.dat`) ### Behavior: 1. Checks if initialization has already occurred via an internal `AtomicBoolean` 2. If not yet initialized, creates an `AssetsZoneRulesInitializer` with the provided context and asset path 3. Registers the initializer with ThreeTenBP's `ZoneRulesInitializer` system 4. Subsequent calls to this method are no-ops (idempotent) ### Throws: - `IllegalStateException` — If the timezone database asset at the specified `assetPath` is not found in the application assets. The exception message includes the missing path (e.g., `"does/not/exist.dat missing from assets"`). Thrown lazily on first timezone query, not at init time. ### Example Usage — Custom Asset Path: ```java public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); // Load timezone database from custom location AndroidThreeTen.init(this, "tzdata/custom_TZDB.dat"); } } ``` ### Example Usage — Error Handling: ```java try { AndroidThreeTen.init(context); // Use JSR-310 APIs Instant now = Instant.now(); } catch (ExceptionInInitializerError e) { if (e.getCause() instanceof IllegalStateException) { Log.e("ThreeTen", "Timezone database not found", e); } } ``` ### Notes: - The asset path is relative to the assets directory root; do not include `assets/` prefix - The asset must be a valid TZDB binary format file (same format as the bundled `org/threeten/bp/TZDB.dat`) - Idempotent: only the first call performs initialization; subsequent calls are ignored - Thread-safe: synchronized via `AtomicBoolean` - The initialization actually occurs lazily when timezone data is first accessed, not when `init()` is called ``` -------------------------------- ### Factory Methods: Parsing Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/api-reference/JSR310-Overview.md Illustrates how to parse date and time strings into objects using ISO format or custom formats. ```APIDOC ## Factory Methods: Parsing ### Description Parse date and time strings into objects using ISO format or custom formats. ### Code Examples ```java LocalDate.parse("2024-01-15"); // ISO format LocalDateTime.parse("2024-01-15T14:30:00"); ZonedDateTime.parse("2024-01-15T14:30:00+05:30[Asia/Kolkata]"); // Custom format DateTimeFormatter format = DateTimeFormatter.ofPattern("MM/dd/yyyy"); LocalDate.parse("01/15/2024", format); ``` ``` -------------------------------- ### Factory Methods: Specific Values Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/api-reference/JSR310-Overview.md Shows how to create date and time objects with specific values, including instants from epoch, durations, and periods. ```APIDOC ## Factory Methods: Specific Values ### Description Create date and time objects with specific values, including instants from epoch, durations, and periods. ### Code Examples ```java // Specify exact values LocalDate.of(2024, 1, 15); LocalDate.of(2024, Month.JANUARY, 15); LocalTime.of(14, 30, 0); LocalDateTime.of(2024, 1, 15, 14, 30); // Time zones ZonedDateTime.of(localDateTime, ZoneId.of("America/New_York")); // Instants from epoch Instant.ofEpochMilli(1234567890000L); Instant.ofEpochSecond(1234567890L); // Durations Duration.ofHours(1); Duration.ofMinutes(30); Duration.ofSeconds(45); Duration.between(start, end); // Periods Period.ofDays(5); Period.ofMonths(1); Period.ofYears(2); Period.between(startDate, endDate); ``` ``` -------------------------------- ### AndroidThreeTen Initialization Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/overview.md The `AndroidThreeTen` class is the main entry point for initializing the library. It provides static methods to initialize the timezone data loading mechanism. ```APIDOC ## `AndroidThreeTen` Class ### Description Static utility class for initialization. ### Methods - `init(Application)` - `init(Context)` - `init(Context, String)` ### Parameters - **`context`** (Context) - The application or activity context. - **`assetPath`** (String) - Optional custom path to the timezone data asset. ``` -------------------------------- ### Legacy Date Formatting (java.util.Date) Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/api-reference/JSR310-Overview.md Demonstrates date formatting using the legacy `java.util.Date` and `SimpleDateFormat`. Note that `SimpleDateFormat` is not thread-safe and `Date` has several design flaws. ```java Date now = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); String formatted = sdf.format(now); // Problems: // - Date not thread-safe (SimpleDateFormat is mutable) // - No timezone information // - Mutable (can be modified after creation) // - Poor API design (months are 0-indexed, years are since 1900) ``` -------------------------------- ### ZonedDateTime Factory and Conversion Methods Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/types.md Illustrates static factory methods for creating ZonedDateTime instances and methods for accessing its components and converting to other types. ```java public final class ZonedDateTime implements Comparable, Serializable { // Static factory methods public static ZonedDateTime now(); public static ZonedDateTime now(ZoneId zone); public static ZonedDateTime of(LocalDateTime dateTime, ZoneId zone); public static ZonedDateTime ofInstant(Instant instant, ZoneId zone); public static ZonedDateTime parse(CharSequence text); // Accessors public LocalDate toLocalDate(); public LocalTime toLocalTime(); public LocalDateTime toLocalDateTime(); public ZoneId getZone(); public ZoneOffset getOffset(); public Instant toInstant(); // Arithmetic public ZonedDateTime plusDays(long daysToAdd); public ZonedDateTime minusHours(long hoursToSubtract); public ZonedDateTime withZoneSameInstant(ZoneId zone); public ZonedDateTime withZoneSameLocal(ZoneId zone); } ``` -------------------------------- ### Initialize ThreeTenABP with Assets Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/architecture.md Ensures thread-safe and idempotent initialization of ThreeTenABP by setting the ZoneRulesInitializer. Only the first caller executes the initialization logic. ```java private static final AtomicBoolean initialized = new AtomicBoolean(); public static void init(Context context, String assetPath) { if (!initialized.getAndSet(true)) { // Only first caller executes this ZoneRulesInitializer.setInitializer(new AssetsZoneRulesInitializer(...)); } // All callers skip this } ``` -------------------------------- ### Prepare for Release Commit Source: https://github.com/jakewharton/threetenabp/blob/trunk/RELEASING.md Commit changes to prepare for a new release version. ```git git commit -am "Prepare for release X.Y.Z." ``` -------------------------------- ### Initialize ThreeTen Android Backport Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/index.md Initialize the library in your Application class's onCreate method. This must be called before using any date/time APIs. ```java public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); AndroidThreeTen.init(this); } } ``` -------------------------------- ### Application to Timezone Query Data Flow Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/architecture.md Illustrates the sequence of events from initializing ThreeTenABP in the application's onCreate method to the first access of timezone data, which triggers the loading of TZDB.dat. ```text MyApplication.onCreate() │ └─> AndroidThreeTen.init(this) │ ├─> Check: already initialized? │ └─> No: Register custom initializer │ └─> ZoneRulesInitializer.setInitializer( new AssetsZoneRulesInitializer(context, "org/threeten/bp/TZDB.dat") ) │ └─> [Initializer stored, not yet used] [Later in app] MyActivity.onCreate() │ └─> ZonedDateTime zdt = ZonedDateTime.now(); │ └─> ZoneId.systemDefault() │ └─> [First timezone access triggers initialization] │ ├─> ZoneRulesInitializer framework checks if initialized │ └─> No: call initializeProviders() │ ├─> context.getAssets().open("org/threeten/bp/TZDB.dat") │ ├─> new TzdbZoneRulesProvider(inputStream) │ │ │ └─> [Parse TZDB binary format into memory] │ └─> ZoneRulesProvider.registerProvider(provider) │ └─> [Provider cached globally] [Subsequent timezone queries use cached provider] ``` -------------------------------- ### Safe Multiple Initialization Attempts Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/errors.md Subsequent calls to `AndroidThreeTen.init(context)` after the first are safely ignored as no-ops. ```java AndroidThreeTen.init(context); // First call initializes AndroidThreeTen.init(context); // Subsequent calls are no-ops ``` -------------------------------- ### Single-Threaded Initialization Pattern Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/api-reference/AndroidThreeTen.md This pattern demonstrates the recommended way to initialize AndroidThreeTen in a single-threaded environment, typically within the Application.onCreate() method. ```java public class MyApp extends Application { @Override public void onCreate() { super.onCreate(); AndroidThreeTen.init(this); } } ``` -------------------------------- ### Initialization Methods Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/api-reference/AndroidThreeTen.md These static methods are used to initialize the JSR-310 date/time support. They should be called once during application startup. ```APIDOC ## init(Application application) ### Description Initializes JSR-310 date/time support using the provided Application context. ### Method static void ### Parameters #### Path Parameters - **application** (Application) - Required - The application context. ### Endpoint N/A (static method call) ``` ```APIDOC ## init(Context context) ### Description Initializes JSR-310 date/time support using the provided Context. ### Method static void ### Parameters #### Path Parameters - **context** (Context) - Required - The context. ### Endpoint N/A (static method call) ``` ```APIDOC ## init(Context context, String assetPath) ### Description Initializes JSR-310 date/time support using the provided Context and a custom asset path for timezone data. ### Method static void ### Parameters #### Path Parameters - **context** (Context) - Required - The context. - **assetPath** (String) - Required - The path to the timezone data assets. ### Endpoint N/A (static method call) ``` -------------------------------- ### Error Handling: Asset File Missing Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/api-reference/AssetsZoneRulesInitializer.md Demonstrates the exception thrown when the specified TZDB asset file is missing or the path is incorrect. This typically results in an IllegalStateException. ```java AndroidThreeTen.init(context, "bad/path.dat"); ZoneId.of("UTC"); // Triggers initialization // Throws: ExceptionInInitializerError // Caused by: IllegalStateException: bad/path.dat missing from assets ``` -------------------------------- ### Use ThreeTen Android Backport APIs Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/index.md Import and use JSR-310 date and time APIs after initialization. Ensure the library is initialized before calling these. ```java import org.threeten.bp.* LocalDate today = LocalDate.now(); ZonedDateTime now = ZonedDateTime.now(ZoneId.of("America/New_York")); ``` -------------------------------- ### Convert Instant to Different Timezones Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/api-reference/JSR310-Overview.md Shows how to convert an Instant to ZonedDateTime objects in different timezones and how to convert a ZonedDateTime from one zone to another while preserving the instant. ```java Instant moment = Instant.now(); ZonedDateTime ny = moment.atZone(ZoneId.of("America/New_York")); ZonedDateTime tokyo = moment.atZone(ZoneId.of("Asia/Tokyo")); ZonedDateTime inTokyo = ny.withZoneSameInstant(ZoneId.of("Asia/Tokyo")); ``` -------------------------------- ### Centralized Error Handling for ThreeTenABP Initialization Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/errors.md Ensures ThreeTenABP is initialized safely, handling potential exceptions during the process. Use this pattern to manage initialization failures and prevent subsequent errors. ```java public class DateTimeManager { private static volatile boolean initialized = false; public static void ensureInitialized(Context context) { if (!initialized) { synchronized (DateTimeManager.class) { if (!initialized) { try { AndroidThreeTen.init(context); initialized = true; } catch (Exception e) { Log.e("DateTimeManager", "Failed to initialize ThreeTen", e); initialized = false; throw new RuntimeException("ThreeTen initialization failed", e); } } } } } public static LocalDate safeParse(String dateString, LocalDate fallback) { try { return LocalDate.parse(dateString); } catch (Exception e) { Log.w("DateTimeManager", "Failed to parse date: " + dateString, e); return fallback; } } public static ZoneId safeZoneId(String zoneId) { try { return ZoneId.of(zoneId); } catch (Exception e) { Log.w("DateTimeManager", "Invalid zone: " + zoneId, e); return ZoneId.systemDefault(); } } } ``` -------------------------------- ### Tag Release Version Source: https://github.com/jakewharton/threetenabp/blob/trunk/RELEASING.md Create an annotated Git tag for the release version. ```git git tag -a X.Y.X -m "Version X.Y.Z." ``` -------------------------------- ### Conflicting Initialization Paths Ignored Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/errors.md When different `init()` overloads are called with different asset paths, the first call initializes the library, and subsequent calls with different paths are silently ignored. ```java AndroidThreeTen.init(context); // Uses "org/threeten/bp/TZDB.dat" AndroidThreeTen.init(context, "custom/path.dat"); // Ignored (already initialized) ``` -------------------------------- ### Gradle Configuration for ThreeTenABP Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/configuration.md Add the ThreeTenABP dependency to your app's build.gradle file. Ensure minSdkVersion is set to 15 or higher. ```gradle android { compileSdkVersion 29 defaultConfig { minSdkVersion 15 // Required: ThreeTen Android Backport minimum targetSdkVersion 29 // Recommended } // Asset configuration (optional if using default structure) sourceSets { main { assets.srcDirs = ['src/main/assets'] } } // ProGuard configuration (automatically applied via consumer rules) buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } } dependencies { api 'com.jakewharton.threetenabp:threetenabp:1.4.9' } ``` -------------------------------- ### Initialize Timezone Providers Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/api-reference/AssetsZoneRulesInitializer.md This method is called by the ThreeTenBP framework to initialize timezone data providers. It opens an asset file, creates a `TzdbZoneRulesProvider`, registers it, and ensures the input stream is closed. ```java @Override protected void initializeProviders() { TzdbZoneRulesProvider provider; InputStream is = null; try { is = context.getAssets().open(assetPath); provider = new TzdbZoneRulesProvider(is); } catch (IOException e) { throw new IllegalStateException(assetPath + " missing from assets", e); } finally { if (is != null) { try { is.close(); } catch (IOException ignored) { } } } ZoneRulesProvider.registerProvider(provider); } ``` -------------------------------- ### Clean and Upload Archives Source: https://github.com/jakewharton/threetenabp/blob/trunk/RELEASING.md Execute the Gradle clean and uploadArchives tasks to build and publish the library. ```gradle ./gradlew clean uploadArchives ``` -------------------------------- ### ThreeTenBP API Usage After Initialization Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/api-reference/AndroidThreeTen.md Demonstrates the usage of various org.threeten.bp classes after AndroidThreeTen has been successfully initialized. These classes provide JSR-310 compliant date and time functionality. ```java import org.threeten.bp.*; // These work after AndroidThreeTen.init(context) LocalDate today = LocalDate.now(); LocalTime time = LocalTime.now(); ZonedDateTime zdt = ZonedDateTime.now(); Instant instant = Instant.now(); ZoneId zone = ZoneId.of("America/New_York"); ``` -------------------------------- ### Late Application Initialization Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/configuration.md Alternatively, initialize ThreeTenABP lazily within an activity's onCreate() method. This approach is safe and idempotent but not recommended for consistent timezone data availability. ```java public class MainActivity extends AppCompatActivity { private static final AtomicBoolean initialized = new AtomicBoolean(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (initialized.compareAndSet(false, true)) { AndroidThreeTen.init(this); } } } ``` -------------------------------- ### Verify Asset Inclusion in APK Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/configuration.md Use the unzip command to verify that the TZDB.dat asset is included in your compiled APK. This confirms the library's assets are correctly packaged. ```bash # Extract and verify the asset is in the APK unzip -l app-debug.apk | grep "org/threeten/bp/TZDB.dat" # Output: org/threeten/bp/TZDB.dat ``` -------------------------------- ### Load TZDB Data from Assets Source: https://github.com/jakewharton/threetenabp/blob/trunk/_autodocs/architecture.md Demonstrates loading TZDB timezone rules from an asset file using an InputStream. The `TzdbZoneRulesProvider` constructor parses the stream, and the stream is closed immediately after. The loaded TZDB data is held in memory by the provider. ```java InputStream is = context.getAssets().open(assetPath); try { TzdbZoneRulesProvider provider = new TzdbZoneRulesProvider(is); // ... provider used ... } finally { is.close(); } ```