Lesson 14 - Diary with a database in Kotlin
In the previous lesson, Date and Time in Kotlin- Parsing and comparing, we learned about date and time in Kotlin.
In today's Kotlin tutorial, we're going to store objects into the
List
collection and work with them further.
At first, I was going to have us create a user database, but we've already
dealt with users several times in this course. Since we now know how to handle
date and time, we're going to make a digital diary. We'll store entries into a
database and print today's and tomorrow's entries. This database won't be an
"actual" database, we'll cover databases later on. All it will be is a
List
in computer memory which will allow the user to add entries,
search for them by date and remove them by specifying a date and time.
Let's create a new application and name it Journal
(don't name
it Diary
since we'll need that name for our class).
Entry
First of all, we'll create a class whose instances we'll store. Let's name it
Entry
. Diary entries will be related to a certain date and time.
They will also contain text, e.g.: January 12, 2016 - Walk the dog
.
Our class might look something like this:
import java.time.LocalDateTime class Entry(var dateTime: LocalDateTime, var text: String) { override fun toString(): String { return "$dateTime $text" } }
Because we want both properties to be readable and writable, we
can just declare them using the constructor parameters and var
.
We'll introduce other collections in a course dedicated to this topic.
All this class is meant to do is store data, so it has no methods (other than
toString()
). You may noticed that the toString()
method doesn't format the date anyhow. We'll get back to it later.
Database
To make the work with entries easier, we'll use the
List
collection. Its methods are identical to the
Array
's but it also allows us to delete the entries.
Since our program will be a bit more complex, we'll separate it into multiple
objects to keep things nice and neat. We've already made the Entry
class, now let's create a Database
object in which our entries will
be stored. There will be a private List
collection of the
Entry
data type this time. Our diary will allow us to add, delete,
and search entries by date. Let's add the Database
class to the
project:
class Database { private var entries: List<Entry> init { entries = listOf() } }
The Database
class will only be used for data manipulation. It
contains an internal collection of entries
which is initialized in
the constructor. We could also initialize it directly without a constructor in
the field declaration:
class Database { private var entries: List<Entry> = listOf() }
Now let's add some methods that will add, delete, and search an entry.
Adding an entry is very simple and straightforward:
fun addEntry(dateTime: LocalDateTime, text: String) {
entries += Entry(dateTime, text)
}
As for the second method, we'll allow the user to search for entries by day.
The method will return a List
of found entries since there can be
multiple entries per day in the database. We'll be able to search for entries
both by date and time or just by date. This way, we can find entries on a
particular day no matter the time. We'll specify our search preferences using a
byTime
boolean
parameter. If it's false
,
our search will be by date only. First, we'll create a List
and add
entries that match the given date. We'll match either full date and time if the
boolean
parameter is true
, or just the date component
of it in case the boolean
parameter is false
. Lastly,
we'll return the list containing all related entries:
fun findEntries(dateTime: LocalDateTime, byTime: Boolean): List<Entry> { var found: List<Entry> = listOf() for (z in entries) { if (((byTime) && (z.dateTime == dateTime)) // filtered by time and date || (!byTime && z.dateTime.toLocalDate() == dateTime.toLocalDate()) // filtered by date only ) found += z } return found }
We used what we learned in previous lessons. In the case of filtering by date
only (without time), we convert dateTime
to LocalDate
and then just compare using ==
whether the data is equal.
To make this code perfect, we'd use "high-order functions", however, we don't know those yet.
We'll finish up the class by adding a method that deletes entries based on a
given time. We'll use the findEntries()
method and remove the found
entries from the list using -=
. We'll be deleting entries of a
specific date and time so the second parameter of the findEntries()
method will be true
:
fun deleteEntries(dateTime: LocalDateTime) { val found = findEntries(dateTime, true) entries -= found }
Diary
Now let's add the last class to our project, which will represent the diary
itself. We'll name it Diary
to keep things simple and clear. It'll
include methods for interacting with the user. Notice how we divide our
application and encapsulate its individual parts. The List
is
encapsulated in the Database
class which wraps it in various
methods handling its contents safely. Let's create a Database
instance in our diary. This way, we separate the data manipulation and
application logic from the user communication and other program inputs/outputs.
The Diary
class is supposed to interact with the user and pass the
entered data to the database.
Let's add a private Database
instance and initialize it in the
constructor:
class Diary { private val database = Database() }
We'll finish the Diary
class in the next lesson, Diary with a database in Kotlin (finishing), when
we'll also finish the whole application.