Date and time functions

Processing date and time in Raku

Raku includes several classes that deal with temporal information: Date, DateTime, Instant and Duration. The three first are dateish, so they mix in the Dateish role, which defines all methods and properties that classes that deal with date should assume. It also includes a class hierarchy of exceptions rooted in X::Temporal.

We will try to illustrate these classes in the next (somewhat extended) example, which can be used to process all files in a directory (by default .) with a particular extension (by default .raku) in a directory, sort them according to their age, and compute how many files have been created per month and how many were modified in certain periods expressed in ranges of months:

sub MAIN( $path = ".", $extension = "raku" ) {
    my DateTime $right = DateTime.now;
    my %metadata;
    my %files-month;
    my %files-period;
    for dir($path).grep( / \.$extension $/ ) -> $file {
        CATCH {
            when X::Temporal { say "Date-related problem", .payload }
            when X::IO { say "File-related problem", .payload }
            default { .payload.say }
        }
        my Instant $modified = $file.modified;
        my Instant $accessed = $file.accessed;
        my Duration $duration = $accessed - $modified;
        my $age = $right - DateTime($accessed);
        my $time-of-day = $file.changed.DateTime.hh-mm-ss but Dateish;
        my $file-changed-date =  $file.changed.Date;
        %metadata{$file} = %( modified => $modified,
                              accessed => $accessed,
                              age => $age,
                              difference => $duration,
                              changed-tod => $time-of-day,
                              changed-date => $file-changed-date);
        %files-month{$file-changed-date.month}++;
        given $file-changed-date {
            when Date.new("2018-01-01")..^Date.new("2018-04-01") { %files-period<pre-grant>++}
            when Date.new("2018-04-01")..Date.new("2018-05-31") { %files-period<grant>++}
            default { %files-period<post-grant>++};
        }
    }

    %metadata.sort( { $^a.value<age> <=> $^b.value<age> } ).map: {
        say $^x.key, ", ",
        $^x.value<accessed modified age difference changed-tod changed-date>.join(", ");
    };
    %files-month.keys.sort.map: {
        say "Month $^x β†’ %files-month{$^x}"
    };

    %files-period.keys.map: {
        say "Period $^x β†’ %files-period{$^x}"
    };
}

DateTime is used in line 2 to contain the current date and time returned by now.

A CATCH phaser is declared in lines 7 to 11. Its main mission is to distinguish between DateTime-related exceptions and other types. These kinds of exception can arise from invalid formats or timezone clashes. Barring some corruption of the file attributes, both are impossible, but in any case they should be caught and separated from other types of exceptions.

We use Instants in lines 12-13 to represent the moment in which the files where accessed and modified. An Instant is measured in atomic seconds and is a very low-level description of a time event; however, the Duration declared in line 14 represents the time transcurred among two different Instants and we will be using it to represent the age.

For some variables, we might be interested in dealing with them with some dateish traits. $time-of-day contains the time of the day the file was changed; changed will return an Instant, but it is converted into a Date (which is Dateish while Instant is not) and then the time of day is extracted from that. $time-of-day will have «Str+{Dateish}␀» type.

We will use the date in this variable to find out the period when the files were changed.

Date.new("2018-01-01")..^Date.new("2018-04-01")

creates a date Range and $file-changed-date is smartmatched against it. Dates can be used this way; in this case it creates a Range that excludes its last element.

This very variable is also used to compute the month of the year when the file was modified. Date is obviously Dateish and then has the month method to extract that property from it.

Duration objects can be compared. This is used in

%metadata.sort({
    $^a.value<age> <=> $^b.value<age>
});

to sort the files by age.

See Also

Containers

A low-level explanation of Raku containers

Contexts and contextualizers

What are contexts and how to switch into them

Control flow

Statements used to control the flow of execution

Enumeration

An example using the enum type

Exceptions

Using exceptions in Raku

Functions

Functions and functional programming in Raku

Grammars

Parsing and interpreting text

Hashes and maps

Working with associative arrays/dictionaries/hashes

Input/Output the definitive guide

Correctly use Raku IO

Lists, sequences, and arrays

Positional data constructs

Metaobject protocol (MOP)

Introspection and the Raku object system

Native calling interface

Call into dynamic libraries that follow the C calling convention

Raku native types

Using the types the compiler and hardware make available to you

Newline handling in Raku

How the different newline characters are handled, and how to change the behavior

Numerics

Numeric types available in Raku

Object orientation

Object orientation in Raku

Operators

Common Raku infixes, prefixes, postfixes, and more!

Packages

Organizing and referencing namespaced program elements

Performance

Measuring and improving runtime or compile-time performance

Phasers

Program execution phases and corresponding phaser blocks

Pragmas

Special modules that define certain aspects of the behavior of the code

Quoting constructs

Writing strings and word lists, in Raku

Regexes

Pattern matching against strings

Sets, bags, and mixes

Unordered collections of unique and weighted objects in Raku

Signature literals

A guide to signatures in Raku

Statement prefixes

Prefixes that alter the behavior of a statement or a set of them

Data structures

How Raku deals with data structures and what we can expect from them

Subscripts

Accessing data structure elements by index or key

Syntax

General rules of Raku syntax

System interaction

Working with the underlying operating system and running applications

Traits

Compile-time specification of behavior made easy

Unicode versus ASCII symbols

Unicode symbols and their ASCII equivalents

Unicode

Unicode support in Raku

Variables

Variables in Raku

Independent routines

Routines not defined within any class or role.

The Camelia image is copyright 2009 by Larry Wall. "Raku" is trademark of the Yet Another Society. All rights reserved.