WEBVTT 1 00:00:01.939 --> 00:00:06.320 so at some point you gonna have to start dealing with dates and times in your 2 00:00:06.320 --> 00:00:09.910 Python programs and although this should be easy there are actually 3 00:00:09.910 --> 00:00:15.129 several pitfalls which just a really they're waiting to trap the unwary 4 00:00:15.129 --> 00:00:18.800 now there is two main sources of problems with dates and times 5 00:00:18.800 --> 00:00:22.890 localization and daylight saving and they can really complicates things if 6 00:00:22.890 --> 00:00:26.640 you don't handle them correctly or not handled correctly now localization 7 00:00:26.640 --> 00:00:30.710 that covers both the time in any particular place and also the 8 00:00:30.710 --> 00:00:34.850 format used to represent dates in that particular location and there's not 9 00:00:34.850 --> 00:00:40.739 necessarily any rhyme or reason to this so as an example in Hoyt Mongolia Lasara 10 00:00:40.739 --> 00:00:45.819 in China and Dhaka in Bangladesh lay on the line running on almost due north-south 11 00:00:45.819 --> 00:00:52.890 but at 10 a.m. in Hoyt is 11 a.m. in Lhasa and 9 a.m. in Dhaka so the UK 12 00:00:52.890 --> 00:00:57.889 is part of the European Union but most of Western Europe is one hour ahead now 13 00:00:57.889 --> 00:00:59.199 daylight savings time 14 00:00:59.199 --> 00:01:03.929 abbreviated to DST that involves moving the clocks forward in spring resulting in 15 00:01:03.929 --> 00:01:07.990 everyone getting up 1 hour earlier to take advantage of the extra daylight as the 16 00:01:07.990 --> 00:01:11.510 Sun rises earlier in the morning now clocks are then put back one hour in 17 00:01:11.510 --> 00:01:16.400 autumn but not every country practices daylight saving though for example the 18 00:01:16.400 --> 00:01:20.690 Philippines don't and that's why I've explained what it is for you in case you are 19 00:01:20.690 --> 00:01:24.420 not aware of what you know daylight saving time is and its practiced in 20 00:01:24.420 --> 00:01:29.120 Australia and I we've actually got at some points in time three different times 21 00:01:29.120 --> 00:01:34.960 zones in Australia covering these and I know at least that many in the united states in fact 22 00:01:34.960 --> 00:01:39.570 most of Africa India and Asia don't mess around with their clocks and even in America 23 00:01:39.570 --> 00:01:43.330 some states such as Arizona don't bother with daylight saving time 24 00:01:43.330 --> 00:01:48.110 at all but in the UK the actual dates when the clock would changed use to be set 25 00:01:48.110 --> 00:01:51.830 each year by a special meeting of Admiralty which meant that you wouldn't 26 00:01:51.830 --> 00:01:55.650 be sure you couldn't be sure that when the change from one year to the next 27 00:01:55.650 --> 00:01:59.810 fortunately countries that do observe daylight savings now make the dates 28 00:01:59.810 --> 00:02:03.770 known for several years in advance and that's so that computer operating 29 00:02:03.770 --> 00:02:08.929 systems like Windows and Linux Mac can maintain files with date which are sent 30 00:02:08.929 --> 00:02:13.440 down to individual computers as part of their normal update process you can imagine the sort of 31 00:02:13.440 --> 00:02:14.569 the chaos 32 00:02:14.569 --> 00:02:18.170 if they didn't know ahead of time when daylight saving was meant to change your 33 00:02:18.170 --> 00:02:21.780 computer and have the wrong date and time so for scientific and computer 34 00:02:21.780 --> 00:02:25.870 applications its usual to work in Coordinated Universal Time that's 35 00:02:25.870 --> 00:02:30.549 abbreviated to UTC is not a misspelling UTC was chosen as a compromise between 36 00:02:30.549 --> 00:02:35.129 the English and French translations so in French the abbreviation would have 37 00:02:35.129 --> 00:02:40.310 been TUC for temps universel coordonné not that I can speak French very well as 38 00:02:40.310 --> 00:02:43.189 the English and the French have a long history of not agreeing on anything 39 00:02:43.189 --> 00:02:48.590 UTC was chosen as a compromise and you may also find UTC interestingly enough 40 00:02:48.590 --> 00:02:51.530 referred to also Zulu time now 41 00:02:51.530 --> 00:02:56.549 dates and times in computer applications and they're usually stored as UTC together 42 00:02:56.549 --> 00:03:02.489 with an offset to represent the number of hours ahead of or behind UTC and a flag 43 00:03:02.489 --> 00:03:07.569 to indicate if daylight savings time applies unless you can be sure that your program 44 00:03:07.569 --> 00:03:12.469 will only ever be used in your current time zone and frankly with the world 45 00:03:12.469 --> 00:03:16.159 wide internet it's really a bad assumption to do that though what you should do 46 00:03:16.159 --> 00:03:18.889 is adopt this method rather than storing local time in other 47 00:03:18.889 --> 00:03:24.629 words you should really be storing your dates as UTC and with that offset as I mentioned for 48 00:03:24.629 --> 00:03:30.959 a particular time zone and now how does this relate to Python well the Python standard library provides three 49 00:03:30.959 --> 00:03:35.799 modules to help us deal with dates and times and that's the time date time and 50 00:03:35.799 --> 00:03:39.709 calendar modules generally if you just dealing with elapsed time and that would 51 00:03:39.709 --> 00:03:42.790 be things like timing how long a program takes to execute 52 00:03:42.790 --> 00:03:46.949 and we will be doing that shortly then the time module will be all we need but if you dealing 53 00:03:46.949 --> 00:03:51.099 with actual dates and times and date time would be more useful now the help for the 54 00:03:51.099 --> 00:03:55.879 time model doesn't include a link so what I'm going to do is open up the link and put the 55 00:03:55.879 --> 00:04:02.310 link in the Resources section so open up a browser and we ill refer to this a few times so it can be useful 56 00:04:02.310 --> 00:04:07.239 to have a look at this page so as can see this is the documentation for the time 57 00:04:07.239 --> 00:04:11.739 and we will as i mentioned with refer to this will come back to this a few times so some of the 58 00:04:11.739 --> 00:04:17.150 documentation like what we've seen in the past with Python can be confusing and 59 00:04:17.150 --> 00:04:21.320 the reason particularly with time in Python is that it discusses the underlying 60 00:04:21.320 --> 00:04:25.470 c libraries Python uses to provide this time support 61 00:04:25.470 --> 00:04:31.060 because c was closely tied to UNIX systems documentation also talks about 62 00:04:31.060 --> 00:04:35.990 UNIX systems a lot but most functions also work on windows in order to make our 63 00:04:35.990 --> 00:04:39.890 code portable across operating systems we're not going to look at any UNIX only 64 00:04:39.890 --> 00:04:42.980 functions were going to restrict ourselves to the general 65 00:04:42.980 --> 00:04:47.980 functions at work on all operating systems and we've discussed most of the terms in 66 00:04:47.980 --> 00:04:52.040 the terminology convention section of the document but we haven't 67 00:04:52.040 --> 00:04:56.170 mentioned rather epok so that c libraries work by storing the number 68 00:04:56.170 --> 00:05:01.100 of seconds since start date and that's referred to generously as the epoc and in Python 69 00:05:01.100 --> 00:05:05.880 on Linux Windows and Mac this is January 1 1970 now 70 00:05:05.880 --> 00:05:10.470 dates before these are represented by negative number although with that said there is a warning that dates 71 00:05:10.470 --> 00:05:14.120 before the start of the epoch may not be handled but if your dealing with historical 72 00:05:14.120 --> 00:05:18.810 dates and it's actually probably a good idea to store them as strings in a 73 00:05:18.810 --> 00:05:24.169 standard format such as you know y y y y dash mm dash dd otherwise 74 00:05:24.169 --> 00:05:28.240 storing and manipulating dates as strings is not really a good idea and 75 00:05:28.240 --> 00:05:33.450 it's note worth noting that a 32 bit signed integer will overflow up to two billion 147 76 00:05:33.450 --> 00:05:39.180 483648 and that many seconds after first of January 77 00:05:39.180 --> 00:05:44.210 1970 is sometime in February 2038 so the bottom line is the 78 00:05:44.210 --> 00:05:49.830 dates this is not going to work as of Feb 2038 because we are going to be overflowing with 32bit integer 79 00:05:49.830 --> 00:05:55.100 so physically the computer wont be able to store the right number to sort of track forward 80 00:05:55.100 --> 00:05:56.610 but hopefully by then 81 00:05:56.610 --> 00:06:00.750 we still got a bit of time all of these computers will be at least 64 bit but if 82 00:06:00.750 --> 00:06:05.160 you happen to be using 32 bit operating system now in 20 odd years time I'll 83 00:06:05.160 --> 00:06:09.890 be asking but secondly we're dealing with dates with them if you are going to be using that ok so a 84 00:06:09.890 --> 00:06:14.120 lot of theory there it is time to get in to do some code so let's go and see some of 85 00:06:14.120 --> 00:06:20.320 the time functions in action so go back to IntelliJ and open up and I've 86 00:06:20.320 --> 00:06:29.020 created a new project going to create a new Python file and call it datecalc 87 00:06:29.020 --> 00:06:32.880 could just have been called literally anything and lets print some time 88 00:06:32.880 --> 00:06:35.910 structures from the epoch date or the system that we're running 89 00:06:35.910 --> 00:06:44.260 on my system is on a Mac so we can start by typing... 90 00:06:44.260 --> 00:06:58.590 .... 91 00:06:58.590 --> 00:07:08.080 ...lets run that and we'll talk about each of the options 92 00:07:08.080 --> 00:07:14.229 so line 3 specifies the number of seconds is 0 so essentially that's gonna represent the 93 00:07:14.229 --> 00:07:18.960 start of the epoch now the GMT time function is also used to convert this 94 00:07:18.960 --> 00:07:24.939 into tuple in GMT time always works in UTC so to get the local time we 95 00:07:24.939 --> 00:07:28.520 can use the local time function like you can see on line 5 and that converts 96 00:07:28.520 --> 00:07:34.169 the time in seconds as the start of the epock as well into a tuple and you can see the first print out you 97 00:07:34.169 --> 00:07:37.030 can see that's clearly a tuple and its got the information relating to the 98 00:07:37.030 --> 00:07:44.169 dates the first example from line 3 output remember I mentioned that Jan 1st 1970 99 00:07:44.169 --> 00:07:48.180 and because we specified 0 its come back to that date automatically and the second 100 00:07:48.180 --> 00:07:52.629 example local time it's picked up on the fact that today in Australia is the 13th of 101 00:07:52.629 --> 00:07:54.430 January 102 00:07:54.430 --> 00:07:59.990 so the date is 13th month is one in 2016 and it's even got the time there 103 00:07:59.990 --> 00:08:07.599 13 49 15 obviously 1:49 in the afternoon 104 00:08:07.599 --> 00:08:11.710 essentially because we didn't specify the epoch it's defaulting to today's date and we 105 00:08:11.710 --> 00:08:16.000 could have also if you wanted to because you can see the third example time.time and that's 106 00:08:16.000 --> 00:08:20.060 actually printed out the number of seconds since the start of an epoch 107 00:08:20.060 --> 00:08:24.389 that's the number of seconds since the first the first 1970 so 108 00:08:24.389 --> 00:08:30.089 we could have change the line on the code on line 5 and if we wanted to 109 00:08:30.089 --> 00:08:32.120 we could have made that time.... 110 00:08:32.120 --> 00:08:36.329 ...to call the time function and run that 111 00:08:36.329 --> 00:08:42.739 and you can see we got the similar results there so the documentation states that GM time 112 00:08:42.739 --> 00:08:47.139 and local time convert the number of seconds into a struct_time 113 00:08:47.139 --> 00:08:52.350 and that's actually named tuple so we are going to be looking at how to create our owned named tuples 114 00:08:52.350 --> 00:08:56.569 later in the course this is a good opportunity to see how to use them so 115 00:08:56.569 --> 00:09:01.049 they just like order tuples that we've seen previously in the course but also 116 00:09:01.049 --> 00:09:05.829 they allow the individual items in a tuple to be accessed using a name and 117 00:09:05.829 --> 00:09:08.720 that can be very useful way to make a code much more readable 118 00:09:08.720 --> 00:09:14.049 what will do is we will assign the current local time to a variable which can be a tuple and use 119 00:09:14.049 --> 00:09:26.309 both methods to access the individual items so you can see what I mean so I'm going to delete those two examples I'm going to put... 120 00:09:26.309 --> 00:10:14.600 .... 121 00:10:14.600 --> 00:10:21.970 ...so we can print the year here 122 00:10:21.970 --> 00:10:26.870 and will just run this first so run that and I made a typo so just change that, that should be 123 00:10:26.870 --> 00:10:37.199 underscore here and try running it again and you can see we got the year and we got two ways of out putting it 2016 the 124 00:10:37.199 --> 00:10:42.000 month and the day and that is the correct date because we've selected local time or using local 125 00:10:42.000 --> 00:10:46.240 time in Australia's as I'm recording the video so you can basically print the year using 126 00:10:46.240 --> 00:10:50.250 the tuple either the way we previously seen using index 0 so that's this first 127 00:10:50.250 --> 00:10:56.019 example time_here 0 in square brackets but we can also use the name so it's time_here 128 00:10:56.019 --> 00:11:01.839 .tm_year and that's the named tuple so there's no practical 129 00:11:01.839 --> 00:11:05.699 difference between the two ways but using the name does make it more obvious 130 00:11:05.699 --> 00:11:10.569 which fields are being accessed because obviously you contrast time_here 131 00:11:10.569 --> 00:11:15.860 is 0 in square brackets as year that's a lot harder than trying to figure out that is a year but this second part here 132 00:11:15.860 --> 00:11:20.079 time_here.tm_year you probably think ok this must be the 133 00:11:20.079 --> 00:11:23.829 year so other than the fact that it's easy to read there is no other differences no 134 00:11:23.829 --> 00:11:27.160 other reason or practical difference between the two ways because both 135 00:11:27.160 --> 00:11:31.050 methods really do return the same value so name tuples are very useful and we will look at 136 00:11:31.050 --> 00:11:34.970 how to create our own as I mentioned after we have covered classes and that is going to be 137 00:11:34.970 --> 00:11:37.339 later in the course but for now whenever you see a 138 00:11:37.339 --> 00:11:41.370 named tuple mention in the documentation you can treat it just like an ordinary 139 00:11:41.370 --> 00:11:45.100 tuple with the advantage of accessing the individual fields I should say in the 140 00:11:45.100 --> 00:11:50.500 tuple by their names so to have a look at how we can measure elapse time Python we are going to create a very 141 00:11:50.500 --> 00:11:55.029 simple reaction time game once the game has started it is gonna wait for a random number 142 00:11:55.029 --> 00:11:58.500 of seconds before displaying a message on the screen and that's going to 143 00:11:58.500 --> 00:12:03.019 measure the time it takes the player to press enter so let us start typing some of the code 144 00:12:03.019 --> 00:12:07.480 because Python does provide a number of ways to measure the elapse time 145 00:12:07.480 --> 00:12:15.790 so we are gonna look at each one in turn so we are going to comment out the code we got in here 146 00:12:15.790 --> 00:12:23.459 actually I'll leave the import in because we need that actually what I'll do is start typing down here so we are going to put... 147 00:12:23.459 --> 00:12:35.949 .... 148 00:12:35.949 --> 00:12:54.199 ....you can see we are specifying a random delay 149 00:12:54.199 --> 00:13:06.009 between 1 and 6 and we are going to sleep for that many seconds so... 150 00:13:06.009 --> 00:13:17.449 ...now we are going to ask them to press Enter to stop.... 151 00:13:17.449 --> 00:13:27.019 ...so we are going to basically recording the start time before enter was press and then end 152 00:13:27.019 --> 00:13:31.329 time afterwards and from there we can figure out how long it took so from there we can put... 153 00:13:31.329 --> 00:13:59.100 ..... 154 00:13:59.100 --> 00:14:05.679 .....same output but we are going to change the parameter we are passing to... 155 00:14:05.679 --> 00:14:07.949 ...... 156 00:14:07.949 --> 00:14:19.420 ..... 157 00:14:19.420 --> 00:14:30.850 ...so that is our program and lets talk about some of the code firstly the on line 158 00:14:30.850 --> 00:14:36.220 12 the from time using import statement in that form is very useful 159 00:14:36.220 --> 00:14:40.320 when experimenting with different implementations of files and modules but 160 00:14:40.320 --> 00:14:43.720 generally speaking you wouldn't leave that in production code so one reason is that 161 00:14:43.720 --> 00:14:48.029 it can be very hard for anyone else to know that my_timer is actually the time 162 00:14:48.029 --> 00:14:51.360 functions from the standard library and that probably expected to be your own 163 00:14:51.360 --> 00:14:55.339 function until they go back to the start of the code and check the imports so once 164 00:14:55.339 --> 00:14:59.490 again remember that your modules can contain hundreds of lines of code and in this example it's 165 00:14:59.490 --> 00:15:02.850 obviously very quick because its all in one screen but you do want to consider 166 00:15:02.850 --> 00:15:07.310 maintenance of your code down the track now the reaction game is pretty simple 167 00:15:07.310 --> 00:15:11.040 uses the random module to generate a random number of seconds between one and 168 00:15:11.040 --> 00:15:15.350 six which you can see on line 17 and then on line 18 it uses time.sleep 169 00:15:15.350 --> 00:15:18.380 where it actually basically sleeps with that amount of time 170 00:15:18.380 --> 00:15:23.630 when it wakes up it stores the current time in start time and displays a message using input 171 00:15:23.630 --> 00:15:28.830 so when the player presses enter then time is stored now because we have used 172 00:15:28.830 --> 00:15:32.750 the time function we can print the start and end times in the player's local time so the 173 00:15:32.750 --> 00:15:39.150 STR if time that stands for string from time that can be used to format the 174 00:15:39.150 --> 00:15:42.910 local time tuple into a more readable form according to a format string its 175 00:15:42.910 --> 00:15:49.080 pass to it so there is a table in the documentation will go and have a look at it shortly but why don't we give this program a bit of a run first to see 176 00:15:49.080 --> 00:16:01.230 what it actually does and we will talk about it more press enter to start 177 00:16:01.230 --> 00:16:10.310 you can see what happened there it started 14:01:19 and finished to 14:01:20 so 178 00:16:10.310 --> 00:16:15.740 my reaction time is point 79 of a second so just under a second so I'm not fully 179 00:16:15.740 --> 00:16:22.970 asleep let's try again a bit slower there and you can see I was .98 second at 180 00:16:22.970 --> 00:16:26.820 that time but you can see that seems to be working and the local time can confirm that 181 00:16:26.820 --> 00:16:29.550 that is the right time if we click on this and have a look 182 00:16:29.550 --> 00:16:34.940 Wednesday 2:01 p.m. as you can see so that is working so getting back to the documentation string 183 00:16:34.940 --> 00:16:45.320 for time let's go have a look at that will search for strft click on that and you can see these various 184 00:16:45.320 --> 00:16:51.400 options and we used the %X in uppercase locale's appropriate time representation so 185 00:16:51.400 --> 00:16:55.800 we just telling it this case that we only want the time component out of the string effectively 186 00:16:55.800 --> 00:17:00.180 out of the date to be shown on the screen so that's a basic example of this 187 00:17:00.180 --> 00:17:03.500 problems with this program though I'll show you one quickly and then I'm going to end the 188 00:17:03.500 --> 00:17:08.520 video and will continue on the next one but one of the first problems we got is I can press enter twice there 189 00:17:08.520 --> 00:17:16.330 and then wait for it to wake up and you can see their my reaction time is points .0001580 190 00:17:16.330 --> 00:17:20.510 that's because I already pressed enter twice and the computer accepted that 191 00:17:20.510 --> 00:17:24.680 enter in advance and that's why I was able to do it so quickly so there's a problem 192 00:17:24.680 --> 00:17:28.240 with that in that I can cheat and also another problem but we'll start talking about 193 00:17:28.240 --> 00:17:31.390 both of those issues and also how to correct those in the next video