Rust Time Module and Chrono Crate Intro πŸ¦€

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey guys my name is Trevor Sullivan and welcome back to my video channel thanks so much for joining me for yet another video that's part of our rust programming tutorial playlist in this playlist We Are exploring the fundamentals of the rust programming language and in the future I'm hoping to create some more advanced videos that cover things like third-party crates end-to-end application building and a lot more now in the last video in this particular playlist if you're following along with my playlist that is we talked about some popular methods that are Exposed on the iterator trait within the rust standard library and how we can use these interesting methods to perform various operations and inspect the data that we find in various types of collections such as vectipes now what I wanted to do in this particular video is start to explore some things pertaining to dates and times as you start to expand and to some real world applications whether it's integrating with a cloud API or writing data to a database maybe you're building an EMR system for medical records and you need to keep track of specific dates and times of when records are created and logs are created and things like that then you're going to need to be able to deal with dates and times within your application the same thing is true when you're dealing with files on the local file system or a remote file system for that matter basically our files have things like creation timestamps modification timestamps last access timestamps and things of that nature so being able to calculate dates and times relative to other dates and times and being able to parse out individual components of timestamps is a really valuable skill that you're going to need as a rust developer so before we jump in to the actual documentation and Hands-On stuff I did want to provide a quick shout out to one of my AI viewers so recently on the list last video that I did called Popular rust iterator methods here somebody left a comment goes by meow squeak here and he mentioned that it's possible to use a variable inside of a format string so right down here we've got these examples right here showing a print line macro call and then we've got index and value being passed in as variable names here unfortunately these format strings or template strings are sometimes called in other languages don't allow you to use any type of expression inside these curly braces but if you do just need to pass in a variable value then you can use this syntax so this is a great example of how the community kind of comes together and by simply leaving a comment on my video I was able to learn something new and then I can disseminate that information with the rest of my viewers so thanks so much to meow squeak for his or her input on this last video here all right so if you'd like to follow along with this rust programming playlist maybe you're new to the language entirely feel free to head out to my channel over at youtube.com Trevor Sullivan if you scroll down just a little bit here you'll see that the rust programming tutorial playlist is featured on the Home tab here you can also go to the playlists tab here and see some other playlists and you can also see my community posts right here so if you subscribe to the channel YouTube will sometimes display these Community posts where sometimes I post polls sometimes I just announce new videos but this is a nice way for you to kind of engage leave comments and kind of test your knowledge if I post one of these polls right here to see if you can get the right answer on the first try all right so with that out of the way let's go ahead and talk about dates and times in the rust programming language now for starters I want to keep things as kind of bare bones as possible I don't want to introduce too much complexity early on in your rust software development journey and to that end I try to depend on the rust standard Library as much as possible without having to bring in third-party libraries or what are known as crates in the rust ecosystem so while I was researching the different ways that we can interact with dates and times in Rust I came across a module here in the standard crate which is called the time module so if you're in the docs for the standard crate go into the time module and then under the time module we have a couple of different data structures that allow us to manage durations in other languages like Powershell or c-sharp you might see those represented as a time span so it's basically a window of time from start to finish could represent maybe a day or an hour or five seconds things like that and you actually get a lot of precision from this data type as well also you can get an instant in time right here as well so you can actually grab like a start time and an end time as separate variables and you can actually subtract one from the other and figure out what the difference which is ultimately the duration of that difference in time is and that could be a measure of performance for example if you want to build some kind of benchmarking application and you need to kick off a timer and then you know cut off the timer calculate the distance and then write that value as your performance metric this would allow you to accomplish that however the built-in time module in the rust standard crate is not going to satisfy a lot of your needs for doing things like date and time operations this is a very restrictive as far as what you can do in here so there is actually a third party crate out there that we're going to need to to bring in called Chrono this is referenced very widely so don't be ashamed of using it and having to kind of step into a third party crate here because we just don't have the capabilities in the standard library that I'm aware of right now but once we install this Chrono crate it's just an open source project here fairly popular with a few thousand stars but it's been downloaded a whole bunch of times if we go over to crates dot IO and search for Chrono here you can see it's been downloaded 105 million times this is a very widely used library for rust and we're going to take a look at some of the functionality not comprehensively because there is a lot of functionality in there but we're going to pull up the documentation for this crate just like we have been for the standard Library here and take a look at some of the different capabilities that we have so let's start things out before we get into Chrono which is a third party Library let's focus on this internal capability that we have within the rust standard crate so what we're going to do is take a look at duration and instant here primarily let's jump over into our vs code editor here again I'm connected to a remote SSH environment which I really love doing because this allows me to use my Windows system locally which I'm very comfortable with but I can still do my software development on a high performance virtual machine that's running on one of my bare metal virtual machine hosts it just runs lexd and I've got a whole playlist series on using lexd if you're interested in spinning up virtual machines and containers with that check out that playlist as well so what we're going to do is start out by creating a new module here in our sample project as you can see I've been working through a lot of different modules here and if you've been keeping up with the playlist you'll see me create a new module each time that we test out some new functionality so I'm going to call this my dateetime.rs and then we're going to put some publicly accessible functions in this module and then we'll be able to call those from our main.rs file here so let's just do a pub mod on my date time now that we've created that file and so now main.rs is aware that we've started a new module here so let's start out by taking a look at duration and instant so what we're going to want to do is import those types into our module here so we'll use the use statement to go into standard and then go into the time module here and then we're going to use the duration so we'll do curly braces here and we'll also import the instance or instant object here I'm thinking of struct instances not instant but those are the two types that we want to work with here just ignore the unused Imports here because it's just warning us that we have unnecessary Imports right here but we're going to use those So eventually those warnings will disappear so let's just create a function here we'll make sure that it is publicly accessible and we'll call it test STD time all right and inside of this module here let's start by taking a look at how to create a duration so duration is pretty simple here if we take a look at our time module go to structs and then choose a duration here also there's a really really nice search feature up here so if you ever want to you can just do a search for duration it'll show you the results right here and you can just click on that so when you're searching through very large libraries which time is not a particularly large module but if you're searching through Chrono for example then it really helps to be able to use the search right up here and you can just use the S key to jump straight into that search box if you've already scrolled way down somewhere you can just hit s and start typing your search query so what we're going to do with duration here is instantiate one and a common pattern that you'll see with some Rust methods is that a struct will Implement these from methods so from seconds from nanoseconds from milliseconds from microseconds and so we can simply call one of these uh static methods on the type in order to get an instance of that particular type and then we can start exploring what we can do with that type beyond that now there's a whole bunch of traits that are implemented on this type as well there's way too many to cover here but a couple of common ones that you'll come across are the add the add a sign and we've also got sub and sub assign and essentially with these methods or these trait implementations are going to allow us to accomplish is to take a duration and subtract or add another duration to it so if we have a duration of one hour and a duration of 15 minutes and another duration of 15 seconds then we we can use those functions that are defined in those traits in order to manipulate the value of our durations so those are really useful traits as we start to kind of calculate things maybe you want to take a look at maybe a race right so you have like an F1 race or a NASCAR race or something like that and maybe you've got 50 laps right so you've got lap time number one lap time number two all the way up through 50 and let's say that you want to aggregate all those values together so you could represent each of those lap times individually as a duration but then if you want to get the total race time for a particular participant in the race then you can simply add all of those durations together and that gives you the total race time for each participant or driver in that particular race right so let's go ahead and instantiate a duration for starters here we'll just use this helper function called from seconds that takes a input of an unsigned 64-bit integer and it will give us a an instance of a duration struct back to our application and as you can see it's really easy to call that so let's go ahead and give that a try in our application so we'll say duration from seconds and then we could say how about 15 seconds here and I'll say let dir 1 equal that value and of course the rust analyzer here has inferred that the dur1 variable is of type duration because that is the data type that's being returned from the from seconds function here so now what we'll do is just do a print line macro here and we're going to use that new trick from squeak Mouse squeak meow squeak I think that was it and we're going to pass in dur1 right here let's go ahead and give that a try and of course in this particular case we're not going to be able to do that because we don't have the necessary trait to convert the duration directly into a string so we'll use the traditional method and say der1 dot and then we can get the value as different data types or units of measure I guess I should say so down here we have as seconds and this will give us an unsigned 64-bit integer we've got as nanoseconds that'll give us an unsigned 128 bit integer as milliseconds as microseconds so the highest Precision that we have here is nanoseconds which I think is 100 100 millionths of a second then we've got microseconds which I think is millionths of a second and then milliseconds which is thousandths of a second so Nanos is the highest Precision micros is next and then the least Precision is milliseconds as far as fractional seconds go so if we wanted to represent it as let's say milliseconds we could just plug that in right here and of course an unsigned 128 bit integer is directly convertible to a string so we should be able to run this and as you can see one of our warnings has disappeared because we've referenced the duration struct so let's do a cargo run I don't know why I'm getting cut off here let's do cargo run and it looks like I'm still calling my old functions in here so let's go to the end of main we're done with iterators for now and we're going to do my date time and call test Standard Time all right so down here we get the milliseconds representation of 15 seconds which of course if you multiply 15 by a thousand you get the number 15 000 so that's pretty straightforward as far as creating a duration now let's create a second duration and see what else we can do with it back in this file here the module will go into this function and we'll say let dir 2 equal duration from let's say milliseconds and this time let's pass in about 5500 milliseconds and so what we'll do is take our first duration right here and then we'll subtract the second duration and because we are dealing with the duration type here it doesn't matter that We're translating from seconds to milliseconds because both of these variables dir 1 and dir 2 both hold the duration type it just doesn't matter that we're just creating one from a different unit of measure because all that's tracked internally by the duration itself so what can we do with this well if we want to subtract dir 2 from dur1 we'll just do der1 Dot and then if we just start typing sub here the rust analyzer extension in vs code will show us this Auto completion and we have this subtract method right here we also have subtract seconds in microseconds or milliseconds or nanoseconds we also have sub assign we also have checked sub so what are all these different things and what do they do well let's take a look at sub here for starters and this is going to take a duration as its input argument which you can also confirm in the documentation right here so if we take a look at the sub trait right down here we should see that there is a function called sub and it takes another duration here and that's going to subtract the other from the instance that we are operating on actually I think it's this one right up here because we're going to pass in a duration and get another duration back all right so we have to make sure that we capture that variable so we'll do let dur 3. equal the result of this I don't know why I did a colon there and we're going to pass in dur 2 for the other input right there all right so what we'll do is say print line and we'll do dir 3 Dot and then say as milliseconds here because we're subtracting milliseconds so we at least want to display millisecond Precision so we can see the difference rather than representing it as seconds which would be a whole number that discards the Precision that we are looking for so 15 minus 5500 milliseconds is going to be well 15 seconds I should say minus 5500 milliseconds is going to be 9 500 milliseconds so we should be expecting 9 500 and sure enough there we go that is 9 500 milliseconds so duration is really nice because you can take multiple durations for different things you can add them together you can subtract them from each other and things of that nature now what would happen if we had a duration of 15 seconds but we tried to remove 15 500 milliseconds well that would give us a negative 500 millisecond resulting value right so is that going to work well no it's actually not so what we do is we get a panic right here which is basically uh aborting the execution of our rest program here because we have an overflow when we subtracted durations now you can't really have a representation of a duration that's negative in value that doesn't really make sense and if you wanted to subtract a duration like you know 15 seconds minus five seconds you would simply subtract five seconds you wouldn't necessarily say go backwards five seconds like subtract 20 and that gives you negative five that doesn't really make much sense right so we can't have negative values for our durations remember when we retrieve the values here so when we say as milliseconds or as seconds or as microseconds or as nanoseconds to actually retrieve the underlying value of the duration we get back this unsigned integer which means we don't have an extra bit that's been allocated for indicating a positive or negative value we can only provide positive values to these durations because they're returning unsigned integers not signed integers so that is solvable we can actually handle this in a much more graceful way than just panicking our program so the program was ultimately panicking right here on line number nine because we can't perform this subtraction operation when we have a value being subtracted that's greater than the input value from der 1 which is 15 seconds or 15 000 milliseconds depending on how you want to visualize it mentally so what we can do is you probably remember we saw when we type dot sub here to subtract a duration from a duration we have some other options here so one of those is called checked sub now checked sub returns if I move my head a little bit out of the way here you can see it returns an option duration now if you're familiar with the option type which you should be if you've been following my playlist then you'll know that the option returns either some value with the underlying generic data type or it returns none and so this is a safe way in Rust for us to check to see if the operation was or wasn't successful what we'll do here is just call checked sub and then once again we just pass in our duration here so we'll do dir 2 here because we want to subtract 15 500 from 15 000 milliseconds and then we'll try to run this again but this time we're going to get this error on line number 10 where we call the print line macro because we are calling the as Millis and because we have an option we don't have the method as Millies directly on this object instead we would have to say dot unwrap or default okay so that's going to give us a value if the operation succeeds or if the value is none because it failed then it'll just give us whatever the default value is and I think it'll probably give us I actually don't know what the value for a default integer or a default duration is I'm going to guess it's probably some kind of zero integer value but we will find out here in just a second so what we're going to do is say unwrap or default and if we do get a value back then we're going to say show me the milliseconds all right and sure enough we get 0 here at the end because the value that was ultimately returned to this variable here by this checked sub operation was an option none type option sum and none are variants of the option enumeration which is a generic type and so what's happening here is we're getting an option and the value of that option is none not some because an error occurred during the subtraction operation and therefore rust's standard Library decided to return a nun to us instead of panicking and aborting execution of our program so this is a safe way for us to continue execution we can use various methods to kind of check the value of the option variable here and see if it's equal to none or not and then kind of figure out what we want to do with it from there so this is just one way of doing it with unwrap or default but there's other ways that you could do things like using an if statement or a match statement or something like that to check the value of this dire3 variable to see if it's some or none all right so let's change this value to something else like 14 500 that should leave us with 500 milliseconds remaining out of fifteen thousand so now if we run this you can see we get 500. so now we've written some safer code in Rust that allows us to handle error conditions in which case our program would normally panic but we're doing it in a safe way that prevents the Panic from occurring all right now there's a bunch of other methods on durations but I'm going to skip over those for now since we're already over 20 minutes in this video so what I'm going to do next is take a look at the instant right so we imported duration and we imported instant here and you'll actually see that it also imported this child type here called the Ops sub and I think it did that when we called the dot sub method earlier but now that we changed it to checked sub I don't think we actually need that anymore so we should be fine with just this all right so let's go ahead and use the instant type now so I'm just going to go after all this code right here I'll just leave it there and we'll say instant Dot and I think we actually need to do a double colon here so what we can do is create a new instant based on now now what exactly does instant give us well the instant type that we have right here is a measure of basically what the current time is now this is based on the internal operating system time and so basically an instant is just going to give us an instant in time and then what we can actually do with that is determine how much time has elapsed from that instant so if we do an instant dot now and say let now equal right now and then we do something like standard thread sleep and let's sleep for a duration this is actually a great example of where a duration is being used in another part of the standard Library so let's say sleep for 200 milliseconds and then we'll do print line and we'll say now dot elapsed and that's actually going to give us a duration so how much time has elapsed between the time that we set the instant the point in time and now right on line 16. well we should have basically 200 milliseconds plus a little bit for overhead maybe but this will allow us to basically measure performance right because we can see what the time Delta is between the first and second call to this instant instantiating it and then calling lapsed here so now we get a duration and we'll just say duration and then we should be able to grab our from or as sorry as milliseconds here and pass that in so then we'll say elapsed time is X and do cargo run and so the elapsed time is 200 milliseconds so basically from a millisecond Precision level thousandth of a second we didn't really have any overhead however if we take a look at the let's say microseconds here and we have a little bit more Precision you can see that we actually have 200 milliseconds plus 177 microseconds so the overhead between the instantiation of the instant and the printing out of the new one is approximately about 200 milliseconds and if we keep running it you can see it stays somewhere around you know 150 to 300 milliseconds somewhere in that range right so this allows us to just capture a point in time then we can do comparisons to that point in time using the instant type as well so that is enough as far as the standard Library goes let's go ahead and take a look at Chrono now because Chrono is the crate that we can use to really start to work with dates and times specifically so we can add dates and times together we can subtract dates and times we can get dates only we can get times only we can get uh different time zones and things of that nature so the Chrono module or crate I should say is pretty interesting and it gives us a lot of functionality that we don't have in the standard Library so let's go back to our my date time module here and we're going to create another function here make sure it's public so we can call it from our main module and we'll call this test Chrono and of course I need to do Pub FN I don't know why I always forget to type that but I seem to do that on a regular basis and so now what we're going to do inside of this function is take a look at some of the different chronotypes here however because we are dealing with a third party crate as far as this playlist on rust is concerned this is the first time that I think I've introduced any third-party crates so we actually have to install this Chrono crate from crates.io using the cargo CLI tool which is our package manager for rust projects very similar to npm for JavaScript projects very similar to Maven for Java project similar to nuget for c-sharp projects and things of that nature so what we want to do is just run the cargo add command in our terminal down here so make sure you're in your project directory where you have your cargo dot toml file let me just find my file list here so here's our cargo.tomo file and if we look at this dependencies section right here you can see that we don't have any declared dependencies because we've only been using the rust standard Library so far but now when we do a cargo add Chrono this is going to install the core feature set for Chrono there are some additional features here that you see with this minus sign in red that have not been installed they're basically what are considered optional features in cargo and what we can do is then plug in to the core functionality of Chrono and start to see what's available if we go back to our cargo.tamil file you'll see that we have the dependencies section now populated with the Chrono entry here and we're running 0.4.28 and if we just check that against the documentation version right here we can see that in this version list right here if we go all the way to the top the latest version does appear to be 0.4.28 also we can go out to crates.io and do a search for Chrono here and this also confirms if we go to the version history tab we can also see that 0428 is the latest version and that was actually just released within the past 24 hours so that's kind of interesting there all right so let's go ahead and see what we can do with Chrono well one of the first things that we have to do is go to our module file here and we have to declare that this module has a external dependency and external dependency on the Chrono crate so the way that we do that is by saying extern crate and then Chrono and you can see that's Auto completed because we've installed that dependency with cargo so now that we've got that imported here let's go down to our test Chrono function and take a look at some of the functionality that's available now one of the most common things that you'll do with a date time library for really any programming language is get whatever the current time is because once you have the current time I can then begin to calculate the difference between now and midnight and see how much time has elapsed in the current day or I could compare now to a Time stored in a database from when a customer placed an order and I can say oh it's been more than four days and the order hasn't shipped yet so we're going to you know refund or give them a discount maybe 10 off of their order right so then you can start to process a refund so it really just helps to kind of start by knowing what your current time is and if your system I'm on a Linux system here in Ubuntu Linux headless server that's running as a VM on one of my bare metal hosts I can just go down to my terminal just run the date command and you can see what UTC is right here so it's currently 6 p.m 6 30 PM approximately over in UTC but I'm actually in UTC -6 so if you run time date CTL right here this command I think I thought I ran this must have ran it on another machine but uh this CLI Tool Time date CTL basically allows you to uh there it is didn't have a dash in it but anyways this command allows you to see what your local and universal time is so local time normally would be offset by a certain offset right a different time zone like negative six negative five whatever it is and of course it depends on daylight savings time as well but if you wanted to determine which different time zones were available we could do time date CTL list Dash versions Or List dash time zones I don't know why I'm thinking versions I'm thinking of dependency versions and then we can kind of tab through just hit the spacebar and kind of tab through these different time zones here I'm going to grab my local time zone America 10 America Denver and then we're going to call the set time zone command and pass in America Denver and once I do that if I run the date command again you should see that now I'm in Mountain Daylight time and of course whenever Daylight Savings Time Changes in the fall that'll change to Mountain Standard Time but my current offset it was 6 30 in UTC so it's 12 30 here so my offset is minus six hours from UTC and if we run time date CTO with no parameters again you can see that my local time is 12 38 UTC is 6 38 pm all right so how do we get UTC time from our application in Rust well what we do is we go out to the Chrono crate and then we look for this type called UTC and just to show you in the documentation here do a search for UTC in the Chrono crate and you'll see this re-export here so UTC itself is not actually defined in the root of the Chrono crate but it's been re-exported so that you don't have to drill all the way down to its formal path where it's actually declared which I think is under um I think it's under naive if I recall correctly I don't remember exactly where it is but UTC is right here oh it's actually under offset it looks like so if we click on that yeah it takes us to Chrono offset UTC anyway UTC has a function on it called now and now is going to return a date time object back to us that we can use to inspect the current date and time based on UTC also there is a today function here that appears to be deprecated and this will return just the date minus the actual time so if you don't need the time precision and you just need to figure out what day it is and then calculate some other day or what the difference between different days is you can just get the date instead of the date and the time and it looks like there's another function here called Date naive that is actually going to replace it so we could maybe figure out where that is but for now let's just go ahead and call UTC now and of course this will return a date time with a generic type of UTC so let's say let UTC now equal Chrono UTC now and then we can explore what possibilities we have with this so we'll do UTC now Dot and there's a whole bunch of functions here that allow you to do things like calculations and things of that nature now you're going to see these references in the Chrono crate to naive and a naive date and time is basically a date and time that's not privy to the current time zone so if we take a look at this right right up here and then we go do let's just do a search for naive uh date and time so here's naive date naive time we have naive week as well and then we have naive date time but if we go to naive date it's basically a calendar date without a time zone so anytime that you see naive date that's what you're dealing with is basically just a date and time but it's not specifying which time zone it's exactly in so what we'll do is say let's format this and so format is going to allow us to extract specific values from this date and time you've got values like a year month month name month number right those are two separate things is what is the month name what is the month number you've got things like the abbreviated month you've got things like the day of the week is it Sunday Monday Tuesday Wednesday Thursday Friday Saturday uh you've got the day of the week numerically as well you've got the current day of the month right so we've got all these very interesting values that we can extract from a date or date and time object or just a time for that matter we've got hour minute second we've got milliseconds nanoseconds all that kind of stuff so how do we know what kind of format we can specify here what this function is asking for is it's basically going to take this date time as input and then it's going to format or structure the output based on whatever format string we feed it and so if you hover over this format here let's actually do a control space here it's going to tell us that we use this strf time and so what this is going to do is it's going to format the time as a string so that we can print it out in a human readable form so if we go over here to our documentation for Chrono and do strf time in the search bar here you'll see this reference to Chrono format that's a module called strf time and then inside of here this specifies all of the different specifiers that we can use in order to extract certain values out of a date and time or a date or a time because you can get all of those independently from each other so let's say that we wanted the year so that's percent capital Y uh these are case sensitive by the way because we all have percent lowercase y as well that'll get you the Gregorian year modulo 100 zero padded to two digits so that would be basically like 01 would be I think 2001. and things like that so let's see if we can get the year the month number or let's actually do this let's do percent B and get the abbreviated month and then let's also get the day of the month that would be percent d right here that's the number of the day of the month anywhere from 1 to 31 of course with certain months only having 30 and February only having 28 or 29 depending on if it's a leap year or not so what we'll do is just say give me a format string as a string pointer a static string of percent capital Y percent B that's the abbreviated month and then we'll do percent uh what do we do here percent lowercase D in order to get the day and then we'll take the result of that format and we will feed it into our print line macro here so let's terminate that print line macro with a semicolon and we'll do cargo run and see what we get back now this is going to take a little bit longer because we actually have to compile the Chrono module or Chrono crate I should say and then let me make sure that I am calling that function from Main it'll say my date time and then test Chrono all right let's try that again as you can see it already compiled Chrono so I didn't need to do that again but now we get 2023 August 31st so that's how we can extract certain values from a UTC date and time now let's say that you wanted the local date and time right so if I do something like percent Capital H which I believe is hours so under time specifiers right here there's kind of a delimiter here we have date specifiers and then time specifiers for hour minute second and that kind of thing so if I do percent h then we're going to get the hour of the day and UTC should be six hours later than my local time so if we do percent H here and run this we have the hour is 18. or we could even say I want to put the hour at the front for whatever bizarre reason I just want to see the hour at the front right and so now I've moved it to the front but then if I want to inspect my local time based on my time zone or the time zone of my Linux server here I can say let local time again that's just a variable you can call it whatever you want to and we'll say Chrono and then uh this is going to be local and then we can do now I almost did UTC again because I'm just very accustomed to using UTC time because it's Universal there's no daylight savings time and I just like as a developer UTC time because it's easy to work with all right so now if we do the same print line statement here we'll just copy that down and then we'll pass in local now instead of UTC now we'll use the exact same format string actually it's local time not local now I don't know why I renamed that let's do cargo run and so now you can see at the very beginning I have hour 12 instead of hour 18. so that's how we can use these format specifiers with that format method to extract individual components of the current date and time and there's lots of different values that you can use here so make sure that you read through these and kind of understand how they work also if you want to get the time zone there's time zone specifiers as well so if we wanted to do percent Z that'll actually give us the current time zone by name I'll do percent Z at the beginning of both of these just so that we can see that the Chrono Library will print out UTC or negative 6 right here so pretty cool stuff and uh you know feel free to try that out on your own make sure that you kind of understand all the different components of it you know play with some different format specifiers and just get comfortable with that stuff now let's talk a little bit about the naive dates so naive dates times and date times are all very similar to each other right it depends if you want just the date just the time or both the date and time together so if we do another search up here and just search for naive you'll see again we've got naive date naive time naive week and naive date time so let's say that we wanted to get a date regardless of the time zone we don't care about the time zone we just want a specific date of the year and so what we'll do is say let date 1 equal naive date and this is going to import the Chrono naive date type which is re-exported at the root of Chrono so that you don't have to drill all the way down to the naive module where that's actually declared just for convenience and then if we do a double colon here you're going to notice that there are a whole bunch of different methods available on this type not the instance of the type but the type itself and these help us to do different calculations with naive dates and times and things like that but we can actually construct a naive date or date time from these methods just like we can with other types we kind of talked about a little bit earlier how there's a from something you know from string whatever type of method that allows us to convert from something to the type that we're trying to instantiate so in this particular case you're actually going to see that there's a lot of crossed out methods here the reason that these methods are crossed out is all due to deprecation so if we kind of take a look through some of the different methods that are declared on the naive date type right here you're going to see on the left hand side as we just scroll through here a lot of these methods have opt at the end I don't know exactly what that stands for maybe it's option I'm just kind of guessing not entirely sure maybe feel free to leave a comment if you happen to know what that suffix means but if we click on the non-opt version then you'll see this deprecation message and so anytime that you see that deprecation message in the documentation for Chrono that is where you'll see the corresponding cross uh I forget what you call that but the it's basically crossed out it's kind of striked out from the list of intellisense here so try to avoid using those deprecated methods because when they come out with Chrono 0.5 I want to say those methods could potentially disappear entirely from the library and that could potentially break your code if you just by default upgrade to the latest version of Chrono so make sure that you're using their newest API to avoid breaking changes down the road now if we want to instantiate one of these one option that we have would be from ISO year week and day and feel free to just explore these different from options here I'm not going to go through every single one just for the sake of time but feel free to play around with these methods in your own environment and just kind of see what they do but for example here we're going to use from ISO year week and day so this would be really interesting if you want to get a certain week of the year right week one through 52 and then get a certain day of that particular week right like I want the Second Sunday of the year or I want the 50th Sunday of the year or the 52nd Sunday of the year to see whatever the last Sunday is going to be so what I could do is specify the year as my first input argument as an integer 32. the reason it's assigned to integer is because you can actually have negative years so if you go BC uh then you can actually have negative years up to like 260 2 000 something like that and uh for a week here it doesn't make sense to have a negative week unless you're going a year backwards but in that case you would just use a different year value here so week is an unsigned 32-bit integer because the only valid values we're going to have are one through 52 as far as weeks go and then the weekday here is actually its own type as well this is an enumeration that's declared under the Chrono crate as well and this gives you a friendly way of accessing the days of the week from Sunday through Monday so this is a nicer way than having to specify the day of the week as just a static string or something that you could potentially make a typo on and the compiler might not be able to check all right so let's try this we'll do naive date from ISO year weekday and then we're going to choose the opt version of that so that we're not using the deprecated version and then we'll pass in a year like 2024 and let's grab the first week of the year and we'll grab a weekday this will import to the enumeration that we just talked about and then I want to figure out when Sunday is so There's Sunday and now we have an option of naive date and that's because again just to catch any potential errors that could occur when we're converting these values to an actual naive date this option type allows us to catch those and handle them as a nun type rather than a populated sum value from the option type and again go back and watch my video on the option type so you have a better understanding of how the option type actually works so now that we have this value we can unwrap it assuming it doesn't throw an error and then we can go ahead and just assign that let's say let unwrapped date equal that and then let's just do a print line here plug in a placeholder and say unwrapped date Dot and see what we can do with this well once again we have the ability to get the format here so we can say all right show me the day of the year right so let's find the format specifier for the day of the year we'll search for strf time and let's find the day of the year so 365 366 there it is day of year is percent J so let's go ahead and put that there and say Day of year is percent J and that'll show us the day of the year that the first week Sunday is is it the very first day of the year January 1st or is it somewhere up through January 7th so let's do a cargo run and Sunday is the seventh day of the year which means the first day of the year is probably Monday right so if we just change the day of the week from Sunday to Monday we should have yep there you go it's January 1st of the year 2024. so just by using rust here we figured out that 2024 first day of January is indeed a Monday we didn't even have to look at a calendar isn't that great all we have to do is write some code and execute it and rust gives us the answers all right so that's one thing that we can do with these naive dates something else that's kind of interesting especially going along with our last video where we talked about iterators in Rust is we can take one of these arbitrary dates that we've constructed and we can iterate over the successive days after that particular date so if we take a look at date one and we say itter actually I think it's going to be unwrapped date so unwrapped date dot iter days so we can iterate over days or we can even iterate over weeks so if you need to grab you know the starting day whatever your naive date is plus seven or plus five or whatever then you can simply iterate iterate over those days and then that's kind of like an infinite iterator so let's say we just want to take four days so we'll use the take method there and then we could say for each and then pass in a closure here which I have another video on so make sure you watch the video on Rust closures and so we'll take that d in as an input argument and then we'll just do a print line and then we'll pass in a D dot format and we'll do a format string that says what the day of the year is which is percent J so we should be starting with let's go back to Sunday here that was the seventh day of the year so we should start with 7 and then do eight nine ten I want to say so basically all we're doing is iterating over the days succeeding the current date taking four of those and then iterating over them and printing out the day of the year that's all we're doing all right so down here yep sure enough we start with Sunday which is the seventh day of the year so January 7th 8th 9th and 10th so that's kind of interesting because if you need to start at a particular day but you need several days after that for some kind of business purpose then you can use this simple iterator here on the naive date in order to retrieve those additional values now there's other ways to construct a naive date as well one of the ways that we can do that there is of course these from methods that I talked about so we've got from ISO your weekday there's another one called year ordinal as well that's kind of interesting so let's copy this line down here and we'll call this let date 2 equal naive date and we'll say from year ordinal and if you don't know what an ordinal year is it actually talks about that in the documentation here so let's do naive uh from yo and if we take a look at the ordinal date link right here it tells us the the ordinal date according to ISO standard 8601 is a pair including the number of the year so 2024 for example and the day of the year so 1 through 60 1 through 366 or 365 if it's not a leap year and I think 2024 actually is a leap year so maybe we can use this to figure out what day of the year the uh leap day is the 366th day right because I think it's every four years so if we do from Yo opt because we want to use the non-deprecated version of it here let's pass in the in 32 the year and the unsigned 32-bit integer which is the day of the year so let's do 2024 comma 366 and if that is a valid day then we should have a value in the option here so let's try to unwrap it let's just pass in date2 dot unwrap Dot format and then we'll get percent uh actually let's get the day of the week by its name we'll do strf time day of week let's do a search for a week here and see if we can figure out when a certain day is all right so percent a is the abbreviated name percent capital A is the full name here so let's do percent a just we get the full name and see what we get back does it throw an error all right so there is a 360 66 today in that year it is a leap year so that's going to be a Tuesday so next year on December 31st that is going to be a Tuesday right and we can confirm that by just grabbing the month let's grab percent capital B and the day of the month as well which is percent D 1-31 so percent B in percent d and just confirm that that's December 31st and sure enough there we go it's December 31st right so anyway those are a couple of day a couple of ways that we can grab a naive date the other one that I wanted to show you though is actually going to allow us to specify a string and a format so what this allows you to do it's it's kind of unique because it allows you to pass in a string with your own custom format but then you get to specify the placeholders where the parser should go look for those individual values right so let's look at an example and I think it'll make a lot more sense that way so let's do naive date and then we're going to call this function here called parse from string and all it does is it takes in two static string values the first one is the actual value containing the year month and day and then the second one is going to be our custom format using the format specifiers as to where each of those placeholders exists in the input string and then it'll be able to parse it out so you have to kind of tell it how to do that so let's say birthday equals parse from string and what we'll do for the input values here is specify 2024 and then I'll do a pipe character that's not really a standard delimiter for dates and times and then I'll do actually let's do two pipe characters yeah let's do three just for fun and then we'll do a month of 09 and then we'll do a double pipe because for some reason our weird format that we're storing in our database is this weird you know pipe delimited with different numbers of pipes format and then we'll do how about the seventh day of September now in order for the parser to figure out how to parse this date here we need to tell it where the year is where the month is and where the day is so in the format string here we just need to go specify these specifiers here in the strf time documentation so we're going to do percent y for starters and then we're gonna do three pipe characters because those are all just literals and then we're going to do the month that's going to be percent m and then we're going to do two pipe characters and then we're gonna do the day of the month which is percent D and so this format right here is telling the parser how to locate the year from this input string and then it knows how to find the month as part of this input string because it's going to pass over these pipe characters and then it's going to pass over two more pipe characters and it's going to grab the day and then it'll give us a naive date based on this weird bizarre format that we came up with and told it how to decode so let's do a print line down here and just to save some time I'm going to do a debug print and we'll grab birthday the other thing you'll notice here is that we get a result because it's possible that it could throw an error a parsing error if we specified an invalid parsing format or just messed up our input value or something like that and so what we can do is say dot ok if there is no error we can actually retrieve the resulting naive date and then we can explore the various values from it and I think it's actually wrapped in option here as well I don't know why it's not showing that here but let's see what we get here for starters and sure enough there we go it printed out the year month and day in a relatively standard format using dashes as delimiters for the year month and day rather than using our bizarre pipe characters so if we were to change this to like 2022 for example the parser is still going to succeed and when we print out the resulting naive date value it works perfectly fine we we successfully parched things and got the value out but if we change the value that we're inputting to like two pipe characters then we're going to get a panic down here because the format that we told it to look for here no longer matches because we only have two pipe characters separating the year and the month instead of the three that we told the parser to actually look for so you will get a panic if the parser is unable to handle that uh it'll it'll actually not necessarily panic but it'll give you this parse error in the result here you can actually get that by doing a result dot error here I think uh sorry birthday dot error and then this will give you back that option wrapping the parse error here and then you can actually see what the issue is so if we were to print out this parse error really quickly it's probably going to tell us that it was like an invalid format or some kind of message like that so let's unwrap the error into the parse error to a pretty print debug output and rerun that and sure enough right here it says parse error invalid and then it does fail right here when we try to run okay because there is no naive date because the parser failed but the parser error was populated so that's why Line 39 works okay where we retrieve the error message and print it out but then ultimately that Panic is happening right here where we try to retrieve the naive date from the wrapping result object so anyways I'm going to kind of cut things off there there's a whole bunch of other functionality inside of Chrono so I will encourage you to read the documentation which is phenomenal here for Chrono again make sure to stay away from the apis that have been deprecated by the Chrono project and just find out what other modules and traits and traits implementations and functions are available on some of these different types it is a very convenient library and I'm sure that you will be working with it heavily if you're building rust applications full time anyway this video is getting pretty long so I'm going to try to cut it shortly out before it hits an hour here thank you again so much for watching and supporting my Channel please don't forget to like this video If you learned anything new from the video any new Concepts please subscribe to the channel that really helps me to grow this channel as I am an independent content creator and leave a comment down below let me know what your feedback is and what other kind of rest programming topics you would be interested in seeing we'll see you in the next video and don't forget to keep track of the rust programming tutorial playlist thanks and take care
Info
Channel: Trevor Sullivan
Views: 3,367
Rating: undefined out of 5
Keywords: rust, rustlang, rust developer, rust programming, rust software, software, open source software, systems programming, data structures, rust structs, rust enums, rust coding, rust development, rustlang tutorial, rust videos, rust programming tutorial, getting started with rust, beginner with rust programming, rust concepts
Id: hZ0hT2LVxCc
Channel Id: undefined
Length: 58min 39sec (3519 seconds)
Published: Fri Sep 01 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.