- As you know,
our application does quite a lot of data handling.
Luckily for us, Rust has an extensive date/time API.
In many ways, it's a bit too extensive
and it's quite complicated,
which is why I decided to cover it
in the examples to help you understand how to dig your way
through all the different options that you have.
So let's take a look.
We're gonna take a look at NaiveDate.
That's the structure that we've used in the application.
It represents a calendar date
without timezone information, okay?
And that's perfect for us.
I don't need timezone information in my application.
So NaiveDate fits the bill perfectly.
If you do need timezone information, don't use NaiveDate,
use DateTime instead.
DateTime is generic.
You've gotta specify a timezone as a type parameter.
We've seen this a few times already in the course.
We've seen DateTime and the timezone type
that I specified was UTC, Universal Coordinated Time.
Okay, anyway, our application uses NaiveDate
and like I said, we're gonna dig into the details now.
We're gonna look in types.rs at the Visit structure.
The Visit structure, if you remember,
it holds the data that I read in from a file.
It contains the start date
and the end date and the description.
In types.rs, there's also a structure called Record.
We haven't seen that yet,
so I'll explain the purpose of that as well.
Okay, so let's go into types.rs.
And I've got the two structures Visit,
which has various implementations and Record,
which we haven't really discussed much yet
and I'll describe that a bit later.
So first things first, NaiveDate and DateTime, in fact,
are defined in the chrono crate.
So in my TOML file, I had to specify the chrono crate
to download it.
It's not part of the standard crate.
It's okay to use it.
Don't feel guilty
about using stuff outside the standard crate.
There were lots and lots
of additional crates that you can use.
For example, in the next lesson, we're going to look
at MySQL and there's a dependency called MySQL,
another crate for MySQL access.
So it's very common
for you to have to specify additional dependencies here
depending on your application requirements.
Okay, back at the types.rs,
the data for a Visit is quite straightforward.
Visit just specifies the start_date,
the end_date, and the description.
And as we've seen already, one of these visits
will be created when the file is read.
When I open the file for reading in my application,
each line basically represents a Visit.
It has a start date
and an end date and a string description.
So one Visit object would basically represent one line
from the file.
And we've already seen
in the file handling module FH, the code that loops
through the file and reads each line.
So we know how to read the string
from the file into memory.
What we're gonna do now is see how to convert that string
into an actual Visit.
So let's close that down.
One other thing to mention while I'm passing by.
Remember, when you're defining structure,
if you want the structure to be accessed elsewhere,
not just in this module but in other files as well,
then you have to declare the structure as public
but you don't specify the implementation as public.
Instead, you can designate individual functions
as being public.
So inside my Visit implementation,
I have two public functions.
A function here,
this function doesn't have a self parameter.
So in other words, it's an associated function,
like a static function in other languages.
You'd call this function like so.
Upon the Visit structure you would invoke from_string.
Like that.
And you'd give it a line of text read in from the file.
Let's imagine that this is the line of text
that's been read in from the file.
So let's just imagine that it's something like that.
So this is what we call when we're doing in our menu,
we say Visit::from_string and we give it a string
with a comma-separated start_date, end_date and description.
And the purpose of the from_string
is to basically create a new Visit object.
So in your code, you could say something
like let v, which is a Visit,
equal the return value.
So that's the kind of understanding of the purpose.
You would call the Visit::from_string associated function,
static function, give it a string
and it gives you back, it passes the string
as we'll see, and gives you back a Visit object.
So this is a factory function.
It creates a Visit object from that date.
And this is what it does.
It takes the incoming string, the string that comes in,
which will be something like this.
And it splits that string at the comma.
When you call the split function, it returns an iterator
and iterate is like a cursor that you can loop through.
I could write a loop on that return value or I can just say
just give me back a list of all the items.
So I just say collect.
That's a common pattern.
We've seen that a few times.
You get back an iterator, you could iterate in a for loop.
Can't be bothered.
Just collect all the items into a list for me.
When I say list, I actually mean vector.
So this should give me back a vector of string slices.
That's interesting, isn't it?
Slices, it'll give me a slice that represents this portion
before the comma and a slice that represents here,
I specified the comma as the separator.
I could have had different formats obviously.
So give me back a slice, which represents that portion
and a slice that represents that portion
and a slice that represents that portion.
And I get an array of those slices.
So tokens is an array of string slices.
What I've been doing in my demos
is I've been specifying data types explicitly
so that you can see clearly what's happening.
A Rust developer would typically not bother.
A Rust developer would typically do that
because the compiler knows
that the collect function returns a vector of string slices.
Why bother extra code?
Well, for the purposes of clarity in my demo,
I thought it's quite useful to do it
but in reality, I wouldn't bother.
Anyway, let's put it back in.
So this vector, element zero
in this vector will be the start date.
So I've got a function here.
You tell date_from_string.
I'm gonna push that discussion to the final demo later on.
So it will take this string here.
Token zero, tokens is my vector of tokens.
Token zero is the start date.
It'll take that start date and convert it into a NaiveDate.
So we will be discussing that function later on.
It's quite easy, but I didn't wanna get distracted just now.
So the Visit object that I'm gonna return, the Visit object
that I'm going to return will have a start date,
which is the string or the date passed from there.
And then tokens one,
so that'll be here, the end_date.
So that gets converted
into a NaiveDate object and that's the end_date.
And then tokens two is free format text at the end.
SoKongsberg is a city in Norway
about an hour and a half west of Oslo.
It's quite a nice city, quite a beautiful city.
And anyway, basically convert that into a string.
At the moment, it's a string slice, so convert it
into a proper string object that I can then own.
And that's the description.
So this is the Visit object that's gonna be created.
Quite a nice function.
That's quite a lot of Python.
Python, where did that come from?
Quite a lot of Rust-related things going on in there.
This is quite idiomatic in usage of Rust features.
So I was quite pleased with that function.
Create a Visit from a string.
It's like a parsed string function, isn't it?
Right, quite straightforward but useful.