Calculating weekdays and dates with Go
Terminal with Mouse Input
The MouseLeft
event comes up if the user clicks and releases the left mouse button. The payload enclosed with the event indicates the coordinates at which the mouse pointer was located at the time of the click. Line 47 needs to dynamically convert the event received as a generic interface{}
type to a ui.Mouse
type; it then uses Y
to access the (vertical) y-value of the click position.
The wdayPick()
function in line 86 determines the clicked weekday. It can do that because the program knows from the UI layout that Sunday is at the click position with a y-value of 4
, Monday at 5
, and so on through Saturday at position 10
. The function discards any other position, returning an error, so that the main program simply ignores the click.
If the user has done their mental arithmetic correctly and selected the right weekday, the condition in line 53 is true, and the BorderStyle.Fg
attribute sets the weekday widget's frame to green. The following call to randDate()
in line 56 fetches a new date task, and the success counter wins
is incremented by one. However, if the user guesses wrong, line 59 colors the widget's frame red and sets wins
back to zero. Life can be hard!
To refresh the success counter graphically, the call to displayTask()
in line 63 changes the widget's contents, and the call ui.Render()
with both widgets as parameters updates the current status in the terminal. To make sure that the red or green border that provides user feedback only appears briefly and then disappears again, line 65 starts a Go routine that runs in parallel; it first sleeps for 200ms thanks to time.After()
, then resets the window's frame to the original White
(which actually looks gray), and displays the whole thing with ui.Render()
. That's how dynamics come into play, thanks simply to the standard parallelism features built into Go.
Text in Color
The text displayed in the widgets can also be colored using termui if so desired – not with an attribute like the widget borders, but using special tags in the text string on display. The date to be calculated appears in black thanks to this, and the number of successfully completed tasks in green; lines 80 to 81 include corresponding color commands in the text to be displayed with (fg:black)
and (fg:green)
.
Tricky Date Arithmetic
Selecting a random day of the year is more difficult than you might think. Sure, most years have 365 days, but in a leap year with 366 days, even February 29 should occur every now and then. Thanks to the Duration
type from the time package, Go offers a method to calculate the time span between January 1 of the year investigated and the same date of the following year. Unfortunately, it refuses to express this in days, but uses hours instead.
The reason for this is the mess that occurs when a leap second [5] or the summer/winter time changeover occurs between two dates. Does that count as a fraction of a day or not? Go forces the programmer to multiply the hour difference by 24 to get the day number – as an indication that this may not be entirely true.
It is easier to use the Unix epoch time on Linux; this gives you the number of seconds that elapsed since January 1, 1970. It does not include leap seconds that have occurred, but gives the same timestamp to the times before and during a leap second. The randDate()
function from line 93 in Listing 1 determines the Unix time for January 1st of the investigated year as well as the time stamp for January 1 of the following year and determines the time difference in seconds.
The rand.Intn()
function then selects a random number between
(inclusive) and the timestamp of January 1 of the following year (exclusive) from the math/rand package and adds the value to the start date. The result is a second timestamp sometime in the current year, which the time.Unix()
function converts into a time.Time
object from the Go standard library, whose month and day are output by Month()
and Day()
. Since Unix seconds are available as int64
and the random functions from math/rand expect and return normal ints, line 102 needs to mediate between the two and convert the types accordingly.
The random number generator provided by Go still has the unpleasant feature of supplying the same random values whenever you call the program; this is unlikely to offer users any lasting training benefits in the long run. For this reason, line 98 taps into a new entropy source, initializes it with the current time in nanoseconds as the seed, and thus creates the new random number generator in the r1
variable. Its Intn()
method therefore comes up with new random sequences each time the dateday
binary is called.
« Previous 1 2 3 Next »
Buy this article as PDF
(incl. VAT)
Buy Linux Magazine
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Support Our Work
Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.
News
-
Canonical Releases Ubuntu 24.04
After a brief pause because of the XZ vulnerability, Ubuntu 24.04 is now available for install.
-
Linux Servers Targeted by Akira Ransomware
A group of bad actors who have already extorted $42 million have their sights set on the Linux platform.
-
TUXEDO Computers Unveils Linux Laptop Featuring AMD Ryzen CPU
This latest release is the first laptop to include the new CPU from Ryzen and Linux preinstalled.
-
XZ Gets the All-Clear
The back door xz vulnerability has been officially reverted for Fedora 40 and versions 38 and 39 were never affected.
-
Canonical Collaborates with Qualcomm on New Venture
This new joint effort is geared toward bringing Ubuntu and Ubuntu Core to Qualcomm-powered devices.
-
Kodi 21.0 Open-Source Entertainment Hub Released
After a year of development, the award-winning Kodi cross-platform, media center software is now available with many new additions and improvements.
-
Linux Usage Increases in Two Key Areas
If market share is your thing, you'll be happy to know that Linux is on the rise in two areas that, if they keep climbing, could have serious meaning for Linux's future.
-
Vulnerability Discovered in xz Libraries
An urgent alert for Fedora 40 has been posted and users should pay attention.
-
Canonical Bumps LTS Support to 12 years
If you're worried that your Ubuntu LTS release won't be supported long enough to last, Canonical has a surprise for you in the form of 12 years of security coverage.
-
Fedora 40 Beta Released Soon
With the official release of Fedora 40 coming in April, it's almost time to download the beta and see what's new.