Fortran

Guide To Learn

Finally, we’re approaching the home stretch. We now have all the ingredients that our program needs: reading the user-input date from the command line, getting the current local time, and taking the difference between the two times. All that’s left now is to test for the values of the two dates and print the message accordingly. The following listing shows the full program.

Listing 10.6 The complete program of the countdown app

program countdown
 
  use mod_datetime, only: datetime, current_time, &      ❶
                          timedelta, get_date_from_cli   ❶
 
  implicit none
 
  type(datetime) :: now, birthday                        ❷
  type(timedelta) :: td                                  ❸
 
  call get_date_from_cli(birthday)                       ❹
  now = current_time()                                   ❺
 
  td = birthday - now                                    ❻
 
  if (now % month == birthday % month &                  ❼
    .and. now % day == birthday % day) then              ❼
    print *, 'Happy Birthday!'                           ❼
  else
    print '(i3, a, 3(i2, a))',        &                  ❽
      td % days, ' days, ',           &                  ❽
      td % hours, ' hours, ',         &                  ❽
      td % minutes, ' minutes, and ', &                  ❽
      td % seconds, &                                    ❽
        ' seconds remaining until your Birthday!'        ❽
  end if
 
end program countdown

❶ Imports the classes and procedures from the module

❷ Declares the datetime instances

❸ Declares the timedelta instance

❹ Gets the date from user input

❺ Gets the current date and time

❻ Computes the time difference

❼ Prints the birthday greeting if same day

❽ Prints the countdown otherwise, specially formatted for pretty display

Since we’re testing whether the dates are matching, we actually don’t use the timedelta instance for the test, but test for the components of the datetime instances directly. Specifically, the month and day of both datetimes must match for the birthday condition to hold. To test that both the month and day match, we use the built-in function all, which we encountered back in section 5.2.11, the “Exercise 2” sidebar. all evaluates as .true. if all the elements in the logical array are .true., and .false. otherwise. If the month and day of the two datetimes don’t match, we use the timedelta instance to report the remaining time in terms of days, hours, minutes, and seconds. Checking for month and day match instead of the timedelta value also saves us from the inconvenient exception that on the day of an actual birthday, the time difference is negative.

Finally, notice that user-defined operators (arithmetic or otherwise) over derived types is yet another layer of abstraction. In this particular scenario, the addition operator + wraps around the type-bound method datetime_minus_datetime, which takes two datetime instances as inputs, which are themselves an abstraction over integer values of year, month, day, and so on. Remember that multiple layers of abstraction add complexity cost to your code–use them only when there’s significant benefit to be gained. In this case, our top-level code (the main program, countdown) is quite simple and easy to read and understand. You can get the complete code for the countdown app from GitHub:

git clone https://github.com/modern-fortran/countdown

If you don’t use git, you can download the whole repository as a zip file from http:// mng.bz/6QeZ.

Ready for more dates and times?

If you’re ready to step up your date and time game in your Fortran projects, I suggest you check out a more fully featured datetime library at http://mng.bz/oPK2. It provides implementations of datetime and timedelta classes with complete sets of arithmetic and comparison operators that you can start using immediately in your own apps. It contains all the functionality that we implemented in this chapter, and much more.

The complete program

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to top