I do not know about Android specifically, but I can give you some guidance on the Java platform. This may apply to Android as well. You will likely need to adjust the file paths for Android specifics.
tl;dr
Use java.nio.file.Files
class to write to local file storage using org.threeten.extra.LocalDateRange
from ThreeTen-Extra library.
Files.write (
Paths.get ( "/Users/some_user/DateRangesExample.txt" ) ,
List
.of (
LocalDateRange.of ( LocalDate.now ( ) , LocalDate.now ( ).plusDays ( 2 ) ) ,
LocalDateRange.of ( LocalDate.of ( 2024 , Month.JANUARY , 23 ) , LocalDate.of ( 2024 , Month.JANUARY , 27 ) )
)
.stream ( )
.map ( LocalDateRange :: toString )
.toList ( )
);
Read.
List < LocalDateRange > localDateRanges =
Files
.readAllLines (
Paths.get ( "/Users/some_user/DateRangesExample.txt" )
)
.stream ( )
.map ( LocalDateRange :: parse )
.toList ( )
;
Get days elapsed with LocalDateTime#lengthInDays
.
File storage
You can write a file to storage to contain your 200 pairs of dates.
The code discussed here assumes you will strictly access the file only from a single thread.
Since Java 7, file storage is managed through the NIO.2 framework. See the free-of-cost tutorial by Oracle.
Let's write a Java record to represent your pair of dates.
package work.basil.example.storage;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
public record DatePair( LocalDate start ,
LocalDate end ,
long days )
{
public DatePair
{
if ( days != ChronoUnit.DAYS.between ( start , end ) )
{
throw new IllegalArgumentException ( "The days argument must be an accurate count of days elapsed between the two dates. Count must be Half-Open, where the beginning is *inclusive* while the ending is *exclusive*." );
}
}
public static DatePair of ( LocalDate start , LocalDate end )
{
return new DatePair ( start , end , ChronoUnit.DAYS.between ( start , end ) );
}
}
Records were added to Java 16. For earlier Java, use a conventional class as seen at bottom of this Answer.
We can use Files.write
and Files.read
to easily write and read your pairs of data in a textual data file. The .write
method by default will (a) create the file if it does not yet exist, and (b) remove all data from an existing file.
Here is a demo app that starts with two pairs of dates, writes those, reads them back, adds a third pair, then does another write and read.
This code replaces all the data in the file every time it writes. You could append instead of replacing, but with so little data it hardly matters.
package work.basil.example.storage;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.Month;
import java.util.ArrayList;
import java.util.List;
public class App
{
public static void main ( String[] args )
{
App app = new App ( );
app.demo ( );
}
@SuppressWarnings ( "branch identical" )
private void demo ( )
{
// Input data.
List < DatePair > pairsOfDates_1 =
List.of (
DatePair.of ( LocalDate.now ( ) , LocalDate.now ( ).plusDays ( 2 ) ) ,
DatePair.of ( LocalDate.of ( 2024 , Month.JANUARY , 23 ) , LocalDate.of ( 2024 , Month.JANUARY , 27 ) )
);
System.out.println ( "pairsOfDates_1 = " + pairsOfDates_1 );
// Write.
Path path = Paths.get ( "/Users/some_user/PairsOfDatesExample.txt" );
this.writePairsOfDates ( pairsOfDates_1 , path );
// Read.
List < DatePair > pairsOfDates_2 = this.readPairsOfDates ( path );
System.out.println ( "pairsOfDates_2 = " + pairsOfDates_2 );
// Add data.
List < DatePair > pairsOfDates_3 = new ArrayList <> ( pairsOfDates_2 );
pairsOfDates_3.add (
DatePair.of (
LocalDate.of ( 2030 , Month.FEBRUARY , 2 ) ,
LocalDate.of ( 2030 , Month.MARCH , 1 )
)
);
System.out.println ( "pairsOfDates_3 = " + pairsOfDates_3 );
// Write data again, replacing existing data file.
this.writePairsOfDates ( pairsOfDates_3 , path );
// Read new file.
List < DatePair > pairsOfDates_4 = this.readPairsOfDates ( path );
System.out.println ( "pairsOfDates_4 = " + pairsOfDates_4 );
}
private void writePairsOfDates ( List < DatePair > dates , Path path )
{
List < String > lines =
dates
.stream ( )
.map ( datePair -> String.join ( "/" , datePair.start ( ).toString ( ) , datePair.end ( ).toString ( ) ) )
.toList ( );
System.out.println ( "lines = " + lines );
try
{
Files.write ( path , lines );
}
catch ( IOException e )
{
throw new RuntimeException ( e );
}
}
private List < DatePair > readPairsOfDates ( final Path path )
{
try
{
List < String > lines = Files.readAllLines ( path );
List < DatePair > datePairs =
lines
.stream ( )
.map ( ( String line ) ->
{
String[] parts = line.split ( "/" );
return DatePair.of ( LocalDate.parse ( parts[ 0 ] ) , LocalDate.parse ( parts[ 1 ] ) );
} )
.toList ( );
return datePairs;
}
catch ( IOException e )
{
throw new RuntimeException ( e );
}
}
}
LocalDateRange
We need not write our own class for the pair of dates. Add the ThreeTen-Extra to access its LocalDateRange
class.
That class simplifies our code.
package work.basil.example.storage;
import org.threeten.extra.LocalDateRange;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.Month;
import java.util.ArrayList;
import java.util.List;
public class App2
{
public static void main ( String[] args )
{
App2 app = new App2 ( );
app.demo ( );
}
@SuppressWarnings ( "branch identical" )
private void demo ( )
{
// Input data.
List < LocalDateRange > range_1 =
List.of (
LocalDateRange.of ( LocalDate.now ( ) , LocalDate.now ( ).plusDays ( 2 ) ) ,
LocalDateRange.of ( LocalDate.of ( 2024 , Month.JANUARY , 23 ) , LocalDate.of ( 2024 , Month.JANUARY , 27 ) )
);
System.out.println ( "range_1 = " + range_1 );
// Write.
Path path = Paths.get ( "/Users/some_user/PairsOfDatesExample.txt" );
this.write ( range_1 , path );
// Read.
List < LocalDateRange > range_2 = this.read ( path );
System.out.println ( "range_2 = " + range_2 );
// Add data.
List < LocalDateRange > range_3 = new ArrayList <> ( range_2 );
range_3.add (
LocalDateRange.of (
LocalDate.of ( 2030 , Month.FEBRUARY , 2 ) ,
LocalDate.of ( 2030 , Month.MARCH , 1 )
)
);
System.out.println ( "range_3 = " + range_3 );
// Write data again, replacing existing data file.
this.write ( range_3 , path );
// Read new file.
List < LocalDateRange > range_4 = this.read ( path );
System.out.println ( "range_4 = " + range_4 );
}
private void write ( List < LocalDateRange > dates , Path path )
{
List < String > lines =
dates
.stream ( )
.map ( LocalDateRange :: toString )
.toList ( );
System.out.println ( "lines = " + lines );
try
{
Files.write ( path , lines );
}
catch ( IOException e )
{
throw new RuntimeException ( e );
}
}
private List < LocalDateRange > read ( final Path path )
{
try
{
List < String > lines = Files.readAllLines ( path );
List < LocalDateRange > localDateRanges =
lines
.stream ( )
.map ( LocalDateRange :: parse )
.toList ( );
return localDateRanges;
}
catch ( IOException e )
{
throw new RuntimeException ( e );
}
}
}
When run:
range_1 = [2023-08-05/2023-08-07, 2024-01-23/2024-01-27]
lines = [2023-08-05/2023-08-07, 2024-01-23/2024-01-27]
range_2 = [2023-08-05/2023-08-07, 2024-01-23/2024-01-27]
range_3 = [2023-08-05/2023-08-07, 2024-01-23/2024-01-27, 2030-02-02/2030-03-01]
lines = [2023-08-05/2023-08-07, 2024-01-23/2024-01-27, 2030-02-02/2030-03-01]
range_4 = [2023-08-05/2023-08-07, 2024-01-23/2024-01-27, 2030-02-02/2030-03-01]
When you need the number of days elapsed, call LocalDateTime#lengthInDays
.
range_4.forEach ( localDateRange -> System.out.println ( localDateRange.toString ( ) + " = " + localDateRange.lengthInDays ( ) ) );
2023-08-05/2023-08-07 = 2
2024-01-23/2024-01-27 = 4
2030-02-02/2030-03-01 = 27
Note that the formats used by LocalDate
& LocalDateRange
when parsing/generating text are standard ISO 8601 formats.
Database
You could use a database for your purpose, but that would be overkill if you read/write the data file in a single thread. If you need to manage data across threads, then use a database engine such as H2.
Converting Java record to conventional class.
package work.basil.example.storage;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.Objects;
public final class DatePair
{
private final LocalDate start;
private final LocalDate end;
private final long days;
public DatePair ( LocalDate start , LocalDate end , long days )
{
if ( days != ChronoUnit.DAYS.between ( start , end ) )
{
throw new IllegalArgumentException ( "The days argument must be an accurate count of days elapsed between the two dates. Count must be Half-Open, where the beginning is *inclusive* while the ending is *exclusive*." );
}
this.start = start;
this.end = end;
this.days = days;
}
public static DatePair of ( LocalDate start , LocalDate end )
{
return new DatePair ( start , end , ChronoUnit.DAYS.between ( start , end ) );
}
public LocalDate start ( )
{
return start;
}
public LocalDate end ( )
{
return end;
}
public long days ( )
{
return days;
}
@Override
public boolean equals ( Object obj )
{
if ( obj == this ) return true;
if ( obj == null || obj.getClass ( ) != this.getClass ( ) ) return false;
var that = ( DatePair ) obj;
return Objects.equals ( this.start , that.start ) &&
Objects.equals ( this.end , that.end ) &&
this.days == that.days;
}
@Override
public int hashCode ( )
{
return Objects.hash ( start , end , days );
}
@Override
public String toString ( )
{
return "DatePair[" +
"start=" + start + ", " +
"end=" + end + ", " +
"days=" + days + ']';
}
}