quinta-feira, 11 de dezembro de 2014

How to have an automatic timestamp update.

The problem

One SQL table has two fields to record the rime of creation and of the last modification. Can the database update these fields automatically when the record is created and updates?

The solution

The table is assumed to have the fields:

CREATE TABLE Users (
  ...,
  created_at DATETIME NOT NULL DEFAULT NOW(),
  modified_at DATETIME,
  ...
);

We have resolved the creation date problem already. Upon creation, created_at will be filled in with the creation date by default, unless another date is passed in.

Now, how can the database update automatically the modified_at field when the field is modified? With an SQL Trigger. If the RDBMS supports triggers, the problem will be solved with code as following:

CREATE TRIGGER TrgUsers_updateTimestamp
  AFTER UPDATE ON Users
    FOR EACH ROW
       SET NEW.modified_at = NOW();

A simple and elegant solution, and thus the applications connecting to the database will not have to worry with timestamps. After any update on any table row, the modified_at field is updated to the current time. This trigger also supports multi-row updates.

segunda-feira, 31 de março de 2014

Singleton pattern in C++, using templates.

The singleton pattern names a programming structure used to replace global variables, without any of their downsizes. A plethora of implementation suggestions have been produced in the previous years. Most are needlessly complicated.

I am posting here a simple and effcient implementation of the singleon pattern. Using function templates and static variables, to get a reference to a singleton instance is no more than getting back a C++ reference. This implementation adds one line to each class that is to be enabled as a singleton, and no inheritance. That is quite useul, since inheritance usually means looking up virtual tables and following them.

First part: the instance function.

instance should return a reference to the given class. C++ Templates come to our help. C++ templates are like C prerocessor macros: they are evaluated at compile time. Thus, they add no overhead whatsoever during the execution of the program.

The function is the following:

template<class T>
inline T &instance() {
  static T instance;
  return instance;
}

That's it: it creates and returns a reference of an instance of the object. That reference is only created once, upon the first invocation of this function. The instance lives wth the application, and is automatically dereferenced before quitting the application. Thus, the destructor is properly called. Any invocation of the function for a given class will return the same instance of that class.

As the function is inlined, a good compiler should take that hint and limit the generated code to a simple return of the reference address.

Second part: the class.

We have a function that retuns us an instance of the class, but we are the to adapt the class to use the function. We need to lock the class against unwanted instantiations. Both the constructor and the destructor should be private or protected. And as we do it, we shuld say that instance<MyClass<> is a friend of the class.

class Game {
public:

  void run() {};

  friend Game &(instance<Game>)();

private:
  Game() {};
  ~Game() {};
};

By making the constructor and the destructor protected, we invalidate any instantiations of the class thet does not come from any friend functions or classes. As the only friend function that we allow to instatiate objects is our template function, we are sure that only through our instance retriever an object of such class can be held.

So that's it, no inheritance and no pesky virtual tables or map dereferences.

Making life easier

One can now get a reference of the global object and run a method there by saying:

  instance<Game>().run();

That is prone to errors and tedious to write, is it not?

What about defining a function to retrieve our code? An inline function takes no more time to execute than a preprocessor macro, and still allows us type checking.

inline Game &
the_game() {
  return instance<Game>();
}

Now we may invoke the run method with:

the_game().run();

You may opt to go one step further and emulate a global variable, without parenthesis:

#define the_game (instance<Game>())

And the invocation will be as simple as:

the_game.run();

I still use the parenthesis.



Comments are, of course, appreciated.

quinta-feira, 16 de janeiro de 2014

A Timer object with angular.js

The problem

Angular JS is probably the best javascript framework around. Simple things are simple and complicated things are possible. As with any other framework in any language, one has to adapt the thought patterns around the intricacies and the peculiarities of the language and the library. One has to take time to learn Angular, but once it is finally understood, the productivity is enhanced.

I have done some web pages with angular. For one I wanted a timer object that I coud stop, start, set the period and the method at will. For instance, within a controller or a directive or any other Angular object:

var timer = new Timer(5000, myFunction, $timeout).start()

This will start the timer and run myFunction every five seconds.

timer.delay(3);

This function will delay the firing of the timer for 3 periods (in the case, 15 seconds.

The rest of the functions should be obvious.

The implementation

The code should be simple to just copy and paste. It uses the $timeout global object from Angular, som make sure angular.js is imported into the page.

var Timer = function(period, meth, $timeout) {
  var tID = null;
  var tPeriod = period || 5000;
  var tDelay = 0;
  var tMeth = meth || null;


  function delay(periods) {
    tDelay = periods;
    return this;
  }

  function setPeriod(period) {
    tPeriod = period || 5000;
    return this;
  }

  function setMethod(meth) {
    tMeth = meth || null;
    return this;
  }

  function stop () {
    if (typeof(tID) != null) {
      $timeout.cancel(tID);
      tID = null;
    }
    return this;
  }

  function start() {
    tID = $timeout(function () {
       if (tDelay) {
         tDelay -= 1;
       } else {
         if (tMeth) {
           tMeth();
         }
       }
       start();
    }, tPeriod);
    return this;
  }

  function restart() {
    stop();
    start();
    return this;
  }

  return {
    'delay': delay,
    'restart': restart,
    'setMethod': setMethod,
    'setPeriod': setPeriod,
    'start': start,
    'stop': stop
  }
}

As always, suggestions are appreciated.

terça-feira, 7 de janeiro de 2014

Emacs - purge session files

The problem

I have always been bothered with the session files left by emacs is user-emacs-directory, normally ~/.emacs.d/. These files have the name session.[a long string of hexadecimal characters] and save the session variables when emacs exits without being explicitely terminated. Like when one ends up the session by the session manager and does not bother to close the emacs window first.

After a few days, a set of session files ends up cluttering the emacs directory. These files lose their purpose once one does not want to restore the session on the next emacs invocation, but they are not purged automatically.

The solution

purge-session-files deletes all session files, preserving the n most recent. n defaults to 1. The function can be called interactively. In such case, the user is given the choice of the number of session files to preserve (defaulting to one).

Here is the code:

(defun purge-session-files (&optional n)
  "Purge all session files but the n more recent files."
  (interactive (list (read-number "Number of files to preserve" 1)))
  (let ((files (directory-files user-emacs-directory t "session.*")))
    (dolist (file (butlast files (or n 1)))
      (delete-file file nil))))

sábado, 4 de janeiro de 2014

XDG Directories for emacs.

Some time ago, I wrote a XDG Directory Specification for GNU Emacs. This is used to assign directories for emacs files under the XDG specification for the home directory.

The named directories are set from the environment variables mentioned in the standard. If no environment variables are present, the following defaults are used:

Symbol Environment variable
(+ /emacs)
Default directory
user-emacs-data-directory XDG_DATA_HOME ~/.local/share/emacs/
user-emacs-config-directory XDG_CONFIG_HOME ~/.config/emacs/
user-emacs-cache-directory XDG_CACHE_HOME ~/.cache/emacs/
user-emacs-lisp-directory `user-emacs-data-directory`/lisp/
user-documents-directory output from xdg-user-dir,
if such executable exists
~/Documents/

Now, the code:

;;; xdg-paths.el --- XDG Base Directory Specification paths for emacs.
;;;
;;;
;;; Copyright ©2011 Francisco Miguel Colaço 
;;; All rights reserved.
;;;
;;; This library is free software; you can redistribute it and/or
;;; modify it under the terms of the GNU Lesser General Public
;;; License as published by the Free Software Foundation; either
;;; version 3 of the License, or (at your option) any later version.
;;;
;;; This library is distributed in the hope that it will be useful,
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
;;; Lesser General Public License for more details.
;;;
;;; You should have received a copy of the GNU Lesser General Public
;;; License along with this library; if not, write to the
;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;;; Boston, MA 02111-1307, USA.
;;;
;;;
;;; Commentary:
;;;
;;; This package sets the directory according to the XDG Base
;;; Directory Specification.  The directories are given by the
;;; environment variables, falling back to the defaults enumerated
;;; in the standard.
;;;
;;; The $XDG_RUNTIME_DIR was not contemplated here, since we found
;;; no practical use for it.
;;;
;;; The defaults (or generated values) are:
;;;
;;;          Symbol                         Default
;;;  user-emacs-data-directory     ~/.local/share/emacs/
;;;  user-emacs-config-directory   ~/.config/emacs/
;;;  user-emacs-cache-directory    ~/.cache/emacs/
;;;  user-emacs-lisp-directory     `user-emacs-data-directory`/lisp
;;;  user-documents-directory      ~/Documents
;;;
;;; Some convenience functions are defined to locate files in these
;;; directories and to add user lisp to load-path.
;;;
;;; Some advantages are:
;;;
;;; Installation:
;;;
;;;   1. put xdg-paths in your own path.
;;;   2. Start your .emacs with (load-library 'xdg-paths) or,
;;;      write (load-library 'xdg-paths) in site-start.el
;;;
;;; Use cases:
;;;
;;; In my .emacs, I simply load a configuration hub file within
;;; user-emacs-config-directory with:
;;;
;;;   (load (locate-user-config-file "conf-init"))
;;;
;;; Within conf-init.el file, all other files are loaded with:
;;;
;;;   (dolist (module (list
;;;                    "edit" "frame" "programming" "tex" "xml"
;;;                    (concat "emacs-version-" (int-to-string emacs-major-version))
;;;                    (concat "window-system-" (symbol-name window-system))
;;;                    (concat "system-type-" (subst-char-in-string ?/ ?- (symbol-name system-type)))
;;;                    (concat "host-" (system-name))))
;;;     (load (locate-user-config-file (concat "conf-" module)) t))
;;;
;;; Adding to path from the user library just becomes:
;;;
;;;     (add-user-lisp-to-path "yasnippet")
;;;
;;; The user documents directory can be made the initial buffer in case
;;; no command line arguments are passed in:
;;;
;;;   (if (eql (length command-line-args) 1)
;;;      ;; No files were passed in the command line.
;;;      (setq initial-buffer-choice user-documents-directory))
;;;
;;;
;;; Caveat Emptor:
;;;
;;; Variable setting and directory initialization were not properly tested.
;;; I have never tested setting previously the directories because the
;;; default results are satisfactory.
;;;
;;;
;;; History:
;;;
;;;  0.1.2: Tom Prince 
;;;    Require cl properly.
;;;    Fix some typos and dead code.
;;;  0.1.1: Francisco Miguel Colaço 
;;;    Removed stale code;
;;;    Replaced eq by zerop in xdg-user-dir.
;;;  0.1: Francisco Miguel Colaço 
;;;    Directory variables;
;;;    Functions to locate files;
;;;    add-to-path and add-user-lisp-to-path;
;;;    xdg-user-dir (depends on xdg-user-dir existing).
;;;
;;;
;;; Future work:
;;;
;;;   1. Make better docstrings (I may have assumed too much).
;;;   3. Add customize support.
;;;   3. Add more functions to cover the full standard.
;;;   4. Add more convenience functions (as needed by others).
;;;   5. Refactor the initialization of the variables.
;;;   6. Make it within the default emacs distribution.
;;;

;;; Code:

(eval-when-compile
  (require 'cl))

;;; Directories definition.
(defvar user-emacs-config-directory nil
  "The directory where the emacs user configuration files are stored at.")


(defvar user-emacs-data-directory nil
  "The directory where the emacs user data and lisp files are stored at.

\\[user-emacs-directory] is set to this directory.")


(defvar user-emacs-cache-directory nil
  "The directory where the emacs user expendable files are stored at.

Files stored here should not be missed when deleted, apart a
temporary loss in speed.")


(defvar user-emacs-lisp-directory nil
  "The directory where the user lisp packages are stored at.

This directory is added to \\[load-path].")


(defvar user-documents-directory nil
  "The directory where the user stores his documents.")



(defun xdg-user-dir (dirname)
  "Given NAME, run 'xdg-user-dir NAME' and return the result in a string.

If the command fails, return NIL."
  (let ((command (concat "xdg-user-dir " dirname)))
    (if (zerop (shell-command command))
 (substring (shell-command-to-string command) 0 -1)
      nil)))


(defun locate-user-file (filename &optional type)
  "Given a file, locate it in the user files.

If TYPE is NIL or 'data, the file will be located in user-emacs-data-directory.

If 'config, it will be located in user-emacs-config-directory.

If 'cache, it will be located in user-emacs-cache-directory.

If 'lisp, it will be located in user-emacs-lisp-directory.

If 'documents, it will be located in user-documents-directory.

If the category is wrong, an error will be signaled.
"
  (expand-file-name filename
      (case type
        ((nil data) user-emacs-data-directory)
        ('config user-emacs-config-directory)
        ('lisp user-emacs-lisp-directory)
        ('cache user-emacs-cache-directory)
        ('documents user-documents-directory)
        (t (error "The category %s is not valid" type)))))


(defun locate-user-config-file (filename)
  "Given a file, locate it in `user-emacs-config-directory`."
  (locate-user-file filename 'config))


(defun locate-user-lisp (filename)
  "Given a file, locate it in `user-emacs-lisp-directory`."
  (locate-user-file filename 'lisp))


(defun add-to-path (directory &optional append)
  "Given DIRECTORY, it it exists and is indeed a directory, add
it to `load-path`."
  (interactive "D")
  (if (file-directory-p directory)
      (add-to-list 'load-path directory append)
      (error "The directory \"%s\" does not exist or isn't a directory." directory)))


(defun add-user-lisp-to-path (directory &optional append)
  "Given DIRECTORY, it it exists and is indeed a directory, add
it to `load-path`."
  (interactive "D")
  (add-to-path (locate-user-lisp directory) append))


;; Set the default variables if they have no name.
(macrolet ((setq-if-null (variable value)
      `(if (null ,variable)
    (setf ,variable ,value)))
    (getdir (variable fallback)
      `(expand-file-name "emacs/" (or (getenv ,variable) ,fallback))))
  (setq-if-null user-emacs-config-directory (getdir "XDG_CONFIG_HOME" "~/.config/"))
  (setq-if-null user-emacs-data-directory (getdir "XDG_DATA_HOME" "~/.local/share/"))
  (setq-if-null user-emacs-cache-directory (getdir "XDG_CACHE_HOME" "~/.cache/"))
  (setq-if-null user-emacs-lisp-directory (expand-file-name "lisp" user-emacs-data-directory))
  (setq-if-null user-documents-directory (or (xdg-user-dir "DOCUMENTS") "~/Documents")))


;; Set the user-emacs-directory to user-emacs-data-directory.
(setf user-emacs-directory user-emacs-data-directory)


;; Add the user lisp directory to path.
(add-to-list 'load-path user-emacs-lisp-directory)


(provide 'xdg-paths)

sexta-feira, 3 de janeiro de 2014

Configuring gEDA

The following files are my configuration for gEDA. gEDA is a suite for electronic design automation (EDA, unsurprisingly). It is a set of loose tools that are supposed to work together, even if with rough edges, to provide an end-to-end solution to design electronic boards.

It actually does a good job. Most of the complaints on gschem (the schematic editor) are not to blame on the program, but on the symbol libraries, which, despite the good work done there, are ridden with annoying inconsistencies. Unlike any commercial applications with free versions, there are no limits on pin number or board size. Once you get the hang of it, it should be enough for most small or medium hobbyist project.

gEDA tools are configured with Guile. Guile is an implementation of scheme. The language is, I grant it, not the best choice for a scientific or technical program, given the profusion of mathematical libraries in python (scipy, numpy, etc). But it does the job and does it well.

File ~/.gEDA/gafrc

(let ((datadir (user-data-dir)))
(scheme-directory (build-path datadir "scheme")) (source-library (build-path datadir "subcircuits")) (let ((symbols-dir (build-path datadir "symbols"))) (for-each (lambda (info) (component-library (build-path symbols-dir (first info)) (second info))) '(("digital" "Digital logic and chips") ("diode" "Diodes") ("graphical" "Graphical Components") ("microcontroller" "Microcontrollers") ("misc" "Miscellaneous") ("passive" "Passive components") ("power" "Power components") ("relay" "Relays") ("subcircuit" "Subcircuit symbols") ("titleblock" "Title blocks") ("transistor" "Transistors"))))) (scheme-directory "./scheme") (component-library "./symbols" "Project Symbols") (source-library "./subcircuits") ;;;; Local Variables: ;;;; mode: scheme ;;;; End:

What this file does is the following: a set of subdirectories are assigned (if they exist) for my own symbols, subcircuits and scripts, in ~/.gEDA/. There will be directories under the directory gschem was started from, normally the project directory. As these configurations are quite common, I have moved them here. I have found them to be quite comprehensive. I do not usually have per directory configuration files, since they are not needed.

File ~/.gEDA/gschemrc

;;; Light colors.
(load (build-path geda-rc-path "gschem-colormap-lightbg"))
(load (build-path geda-rc-path "print-colormap-lightbg"))

;;; Set the window size.
(window-size 1100 650)

(define default-titleblock "border-A3L.sym")

(paper-size 16.54 11.69) ; A3
(output-color "enabled")
(output-type "extents")
(output-orientation "landscape")

(image-color "enabled")

(load-from-path "auto-uref.scm")
(add-hook! add-component-hook auto-uref)
(add-hook! copy-component-hook auto-uref)

(auto-uref-set-page-offset 100)

;;;; Local Variables:
;;;;   mode: scheme
;;;; End:

The titleblock

I do not fancy the large symbols in gschem libraries. It wastes a lot of paper for nothing. As I cannot reduce the symbols without implementing the whole library, I chose to widen the paper, that is, to enlarge the titleblock and the borders of the paper. Once the schematic is printed, it will be printed under the new units, since I just print it complete without margins on A3 paper.

The symbol files can be found at this Google Drive directory. There is a symbol for a title block (with useful attributes), A3 landscape and A4 portrait borders. The following image is a screenshot of gschem running under Linux with the title block and borders I have provided.

Please provide suggestions to improve these files

quinta-feira, 2 de janeiro de 2014

An exemplary module of good practices in Haskell

Haskell is not an easy language. It takes a lot of mind wrapping to understand monads, but once you do, you lose all capability to explain it. I shall not even try to explain monads. I prefer to show by example how haskell should be written.

You can, simplistically, say a monad is data with a context. Just like with physical units, like 2m or 2Kg. Two metres are different from two kilogrammes. One pertains to length, another to mass. In monadic speak, it would be "Metre 2" or "Kilogramme 4", since monads are prefixed. You could add metres with metres, but not metres with kilogrammes. And thus type safety comes into being actually useful.

The following code is here. It has been edited in Literate Haskell and transformed with Pandoc to HTML. The original HTML file, as it came out of Pandoc, can be found here.


A Date/Time Period

  • DESCRIPTION: A period that contains dates or times.
  • AUTHOR: Francisco Miguel Colaço <>
  • DATE: 2013-12-23

Summary

The Period class describes a possibly infinite period of dates and times. It has functions that assess if a date or a moment in time belongs in a given periods. It has also fuctions that create new intervals with reference to the current moment (under the IO Monad).

Implementation

Declarations

This package uses several Haskell language extensions. These extensions are not deprecated, nor considered harmful.

{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE StandaloneDeriving #-}
module Data.Period where
import Control.Monad
import Data.Data
import Data.List
import Data.Maybe
import Data.Time
import Data.Time.Calendar
import Data.Time.Calendar.WeekDate

The Period Data Type

A period can extend From a start date or time, Until an end time, with no beginning, Between two times (or dates), or a bottom value of Infinite, that is, from the start to the end of times. To be precise, one could make periods out of integers or numbers. The only requisite is that the type variable is orderable and showable. All numbers are. Of course, one could restrict the period type variable to dates and times only by having them belong to the Data.Time.Format.FormatTime class. We opted not to.

Using GADTs, the type constraints of the type variable are made right at the constructors, and thus reflect themselves through all the functions that use the Period data type.

-- | An interval of orderable and showable values.  The period can be `From` a
-- determined time with no end; `Until` a given time and with no start;
-- `Between` two times; or `Infinite`, meaning without start or end.
data Period a where
  From     :: (Ord a, Show a) => a -> Period a
  Until    :: (Ord a, Show a) => a -> Period a
  Between  :: (Ord a, Show a) => a -> a -> Period a
  Infinite :: Period a
instance Show (Period a) where
  show (From start) = "From " ++ show start
  show (Until end) = "Until " ++ show end
  show (Between start end) = "Between " ++ show start ++ " and " ++ show end
  show Infinite = "All times"
deriving instance Typeable1 Period
deriving instance (Data a, Ord a, Show a) => Data (Period a)

A DatePeriod is a period of dates (days). A TimePeriod is a period of UTC times. Both values are defined in Data.Time.

Periods can also be set in terms of any orderable and showable types, like enumerations or numbers. The library is to be used with dates and times.

Date and Time Periods

type DatePeriod = Period Day
type TimePeriod = Period UTCTime

Conversions between the two period types are possible.

-- | Converts from a time period to a date period.  Truncates the period to the
-- dates, disregarding the day fractions.
toDatePeriod :: TimePeriod -> DatePeriod
toDatePeriod (From start) = From (utctDay start)
toDatePeriod (Until end) = Until (utctDay end)
toDatePeriod (Between start end) = Between (utctDay start) (utctDay end)
toDatePeriod Infinite = Infinite

-- | Converts from a date period to a time period.  The period is counted from
-- the start of the first day to the end of the last.
toTimePeriod :: DatePeriod -> TimePeriod
toTimePeriod (From start) = From (UTCTime start 0.0)
toTimePeriod (Until end) = Until (UTCTime end 86399.999999)
toTimePeriod (Between start end) = Between (UTCTime start 0.0) (UTCTime end 86399.999999)
toTimePeriod Infinite = Infinite

Period Limit Tests

A period is closed when it has no upper end. That is, only Infinite and From periods are open. All others are closed.

isClosed Infinite
False
isClosed $ Until $ fromGregorian 2013 1 1
True
fromNow >>= return . isClosed
IO False
-- | Tells if the period has an end.
isClosed :: Period a -> Bool
isClosed Infinite = False
isClosed (From _) = False
isClosed _ = True

Any period may or may not have have a start or an end. As it may have not, the enquiry can fail. So, the answer is wrapped in the Maybe monad.

From periods have a start, but not an end. Until periods have only an end. Between periods have both. Infinite has neither.

-- | Returns the start of the period (in the Maybe Monad), if it has one.
periodStart :: Period a -> Maybe a
periodStart (From start) = Just start
periodStart (Between start _) = Just start
periodStart _ = Nothing 

-- | Returns the end of the period (in the Maybe Monad), if it has one.
periodEnd :: Period a -> Maybe a
periodEnd (Until end) = Just end
periodEnd (Between _ end) = Just end
periodEnd _ = Nothing 

Value Containment

contains is meant to be used infix. Tells if a given period contains the given date. A period has inclusive bounds. A date exactly equal to one of the bounds is still contained in it.

contains :: Period a -> a -> Bool
contains Infinite _ = True
contains (From start) now = now >= start
contains (Until end) now = now <= end
contains (Between start end) now = (now >= start) && (now <= end)

belongs is contains with the arguments splitted. One date belongs to a period when such period contains the date.

From (fromGregorian 2013 1 1) `contains` (fromGregorian 2013 1 1)
True
(liftM2 contains) thisYear (return $ fromGregorian 2012 1 1)
IO False
(liftM2 contains) fromNow getCurrentTime
IO True
(liftM2 belongs) getCurrentTime fromNow
IO True
belongs :: a -> Period a -> Bool
n `belongs` p = p `contains` n

Constructors Reported to the Current Date

Constructors are provided that extend from or until the current day and time. The constructors are computed under the IO Monad, since they have to compute the current date.

-- | Returns a time period that extends from the present time.
fromNow :: IO TimePeriod
fromNow = liftM From getCurrentTime

-- | Returns a time period that extends until the present time.
untilNow :: IO TimePeriod
untilNow = liftM Until getCurrentTime

-- | Returns a day period that extends from the present day.
fromToday :: IO DatePeriod
fromToday = liftM (From . utctDay) getCurrentTime 

-- | Returns a day period that extends until the present day.
untilToday :: IO DatePeriod
untilToday = liftM (Until . utctDay) getCurrentTime

Common Date Periods

Date periods for the current year, the current month and the current week are often requested. These have to be computed under the IO Monad, since they determine the current time.

-- | Returns a date period that spans throughout the current year.
thisYear :: IO DatePeriod
thisYear = do
  (yr, _, _) <- (liftM $ toGregorian . utctDay) getCurrentTime
  return $ Between (fromGregorian yr 1 1) (fromGregorian yr 12 31)

-- | Returns a date period that spans throughout the current month.
thisMonth :: IO DatePeriod
thisMonth = do
  (yr, mo, _) <- (liftM $ toGregorian . utctDay) getCurrentTime
  return $ Between (fromGregorian yr mo 1) (fromGregorian yr mo $ gregorianMonthLength yr mo)

-- | Returns a date period that spans throughout the week.
thisWeek :: IO DatePeriod
thisWeek = do
  (yr, wk, d) <- (liftM $ toWeekDate . utctDay) getCurrentTime
  return $ Between (fromWeekDate yr wk 1) (fromWeekDate yr wk 7)

A time period is quite requested: the one that comprises the current day. This period has to be computed under the IO Monad. The implementation has two flaws: do not account for end days and fall short one microssecond from the real end of the day.

-- | Returns a time period that comprises the current day.
thisDay :: IO TimePeriod
thisDay = do
  today <- liftM utctDay getCurrentTime
  return $ toTimePeriod $ Between today today

A very frequent query is to know if a given period contains the current day or time. These queries have to be made inside the IO Monad.

containsNow Infinite
IO True
fromToday >>= containsToday
IO True
thisYear >>= containsToday
IO True
fromNow >>= containsNow
IO True

Containment of the Current Date

-- | Tells if a date period contains the current day.
containsToday :: DatePeriod -> IO Bool
containsToday period = do
  now <- getCurrentTime
  return $ period `contains` utctDay now

-- | Tells if a time period contains the current time.
containsNow :: TimePeriod -> IO Bool
containsNow period = do
  now <- getCurrentTime
  return $ period `contains` now