NAME
Moment - class that represents the moment in time
VERSION
version 1.2.0
SYNOPSIS
Moment is a Perl library. With this library you can create object that represent some moment in time.
The library works with date and time in the UTC timezone. The purpose of not supporting other timezones is to force good practice in working with time. The best way to manage time in program is to store and to work with time in UTC.
There are 3 ways you can create new object with the new() constructor:
my $some_moment = Moment->new(
# dt format is 'YYYY-MM-DD hh:mm:ss'
dt => '2014-11-27 03:31:23',
);
my $other_moment = Moment->new(
year => 2014,
month => 1,
day => 3,
hour => 4,
minute => 2,
second => 10,
);
my $one_more_moment = Moment->new(
# Unix time (a.k.a. POSIX time or Epoch time)
timestamp => 1000000000,
);
You can also use now() constructor to create object that points to the current moment in time:
my $now = Moment->now();
When you have an object you can you use methods from it.
Here are the methods to get the values that was used in constructor:
#'2014-11-27 03:31:23'
my $dt = $moment->get_dt();
my $d = $moment->get_d();
my $t = $moment->get_t();
my $year = $moment->get_year();
my $month = $moment->get_month();
my $day = $moment->get_day();
my $hour = $moment->get_hour();
my $minute = $moment->get_minute();
my $second = $moment->get_second();
# Unix time (a.k.a. POSIX time or Epoch time)
my $number = $moment->get_timestamp();
You can find out what is the day of week of the moment that is stored in the object. You can get scalar with the weekday name:
# 'monday', 'tuesday' and others
my $string = $moment->get_weekday_name();
Or you can get weekday number (specifying what weekday should be number one):
my $number = $moment->get_weekday_number( first_day => 'monday' );
Or you can test if the weekday of the moment is some specified weekday:
$moment->is_monday();
$moment->is_tuesday();
$moment->is_wednesday();
$moment->is_thursday();
$moment->is_friday();
$moment->is_saturday();
$moment->is_sunday();
You can test if the year of the moment is leap with the method:
$moment->is_leap_year();
If you have 2 Moment objects you can compare them with the cmp() method. The method cmp() works exaclty as cmp builtin keyword and returns -1, 0, or 1:
my $result = $moment_1->cmp($moment_2);
The Moment object is immutable. You can't change it after it is created. But you can create new objects with the methods plus(), minus() and get_month_start(), get_month_end():
my $in_one_day = $moment->plus( day => 1 );
my $ten_seconds_before = $moment->minus( second => 10 );
# create object with the moment '2014-11-01 00:00:00'
my $moment = Moment->new(dt => '2014-11-27 03:31:23')->get_month_start();
# create object with the moment '2014-11-30 23:59:59'
my $moment = Moment->new(dt => '2014-11-27 03:31:23')->get_month_end();
DESCRIPTION
Features and limitations of this library:
Library is as simple as possible
Class represents only UTC time, no timezone info
Object orentied design
Object can't be changed after creation
The precise is one seond
Working with dates in the period from '1800-01-01 00:00:00' to '2199-12-31 23:59:59'
Dies in case of any errors
No dependencies, but perl and its core modules
Plays well with Data::Printer
Using SemVer for version numbers
METHODS
new()
Constructor. Creates new Moment object that points to the specified moment of time. Can be used in 3 different ways:
my $some_moment = Moment->new(
# dt format is 'YYYY-MM-DD hh:mm:ss'
dt => '2014-11-27 03:31:23',
);
my $other_moment = Moment->new(
year => 2014,
month => 1,
day => 3,
hour => 4,
minute => 2,
second => 10,
);
my $one_more_moment = Moment->new(
# Unix time (a.k.a. POSIX time or Epoch time)
timestamp => 1000000000,
);
Dies in case of errors.
now()
Constructor. Creates new Moment object that points to the current moment of time.
my $current_moment = Moment->now();
get_timestamp()
Returns the timestamp of the moment stored in the object.
The timestamp is also known as Unix time, POSIX time, Epoch time.
This is the number of seconds passed from '1970-01-01 00:00:00'.
This number can be negative.
say Moment->new( dt => '1970-01-01 00:00:00' )->get_timestamp(); # 0
say Moment->new( dt => '2000-01-01 00:00:00' )->get_timestamp(); # 946684800
say Moment->new( dt => '1960-01-01 00:00:00' )->get_timestamp(); # -315619200
The value that return this method is in the range [-5_364_662_400, 7_258_118_399].
get_dt()
Returns the scalar with date and time of the moment stored in the object. The data in scalar is in format 'YYYY-MM-DD hh:mm:ss'.
say Moment->now()->get_dt(); # 2014-12-07 11:50:57
The value that return this method is in the range ['1800-01-01 00:00:00', '2199-12-31 23:59:59'].
get_d()
Returns the scalar with date of the moment stored in the object. The data in scalar is in format 'YYYY-MM-DD'.
say Moment->now()->get_d(); # 2014-12-07
The value that return this method is in the range ['1800-01-01', '2199-12-31'].
get_t()
Returns the scalar with time of the moment stored in the object. The data in scalar is in format 'hh:mm:ss'.
say Moment->now()->get_t(); # 11:50:57
The value that return this method is in the range ['00:00:00', '23:59:59'].
get_year()
Returns the scalar with year of the moment stored in the object.
say Moment->now()->get_year(); # 2014
The value that return this method is in the range [1800, 2199].
get_month()
Returns the scalar with number of month of the moment stored in the object.
say Moment->now()->get_month(); # 12
The value that return this method is in the range [1, 12].
Method return '9', not '09'.
get_day()
Returns the scalar with number of day since the beginning of mongth of the moment stored in the object.
say Moment->now()->get_day(); # 7
The value that return this method is in the range [1, MAX_DAY]. Where the MAX_DAY depend on the month:
1 => 31,
2 => 28, # 29 on leap years
3 => 31,
4 => 30,
5 => 31,
6 => 30,
7 => 31,
8 => 31,
9 => 30,
10 => 31,
11 => 30,
12 => 31,
Method return '7', not '07'.
get_hour()
Returns the scalar with hour of the moment stored in the object.
say Moment->now()->get_hour(); # 11
The value that return this method is in the range [0, 23].
Method return '9', not '09'.
get_minute()
Returns the scalar with minute of the moment stored in the object.
say Moment->now()->get_minute(); # 50
The value that return this method is in the range [0, 59].
Method return '9', not '09'.
get_second()
Returns the scalar with second of the moment stored in the object.
say Moment->now()->get_second(); # 57
The value that return this method is in the range [0, 59].
Method return '9', not '09'.
get_weekday_name()
Return scalar with the weekday name. Here is the full list of strings that this method can return: 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'.
say Moment->now()->get_weekday_name(); # sunday
get_weekday_number()
my $number = $moment->get_weekday_number( first_day => 'monday' );
Returns scalar with weekday number.
The value that return this method is in the range [1, 7].
You must specify value for the first_day parameter. It should be one of: 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'.
my $m = Moment->new( dt => '2015-04-27 00:00:00'); # monday
$m->get_weekday_number( first_day => 'monday' ); # 1
$m->get_weekday_number( first_day => 'sunday' ); # 2
is_monday()
Returns true value is the weekday of the moment is monday. Otherwise returns false value.
is_tuesday()
Returns true value is the weekday of the moment is tuesday. Otherwise returns false value.
is_wednesday()
Returns true value is the weekday of the moment is wednesday. Otherwise returns false value.
is_thursday()
Returns true value is the weekday of the moment is thursday. Otherwise returns false value.
is_friday()
Returns true value is the weekday of the moment is friday. Otherwise returns false value.
is_saturday()
Returns true value is the weekday of the moment is saturday. Otherwise returns false value.
is_sunday()
Returns true value is the weekday of the moment is sunday. Otherwise returns false value.
is_leap_year()
Returns true value is the year of the moment is leap. Otherwise returns false value.
cmp()
Method to compare 2 object. It works exactly as perl builtin 'cmp' keyword.
my $result = $moment_1->cmp($moment_2);
It returns -1, 0, or 1 depending on whether the $moment_1 is stringwise less than, equal to, or greater than the $moment_2
say Moment->new(dt=>'1970-01-01 00:00:00')->cmp( Moment->new(dt=>'2000-01-01 00:00') ); # -1
say Moment->new(dt=>'2000-01-01 00:00:00')->cmp( Moment->new(dt=>'2000-01-01 00:00') ); # 0
say Moment->new(dt=>'2010-01-01 00:00:00')->cmp( Moment->new(dt=>'2000-01-01 00:00') ); # 1
plus()
Method plus() returns new object that differ from the original to the specified time. The class of the new object is the same as the class of the variable on which you run method.
my $new_moment = $moment->plus(
day => 1,
hour => 2,
minute => 3,
second => 4,
);
You can also use negative numbers.
my $two_hours_ago = $moment->plus( hour => -2 );
Here is an example:
say Moment->new(dt=>'2010-01-01 00:00:00')
->plus( day => 1, hour => 2, minute => 3, second => 4 )
->get_dt()
;
# 2010-01-02 02:03:04
minus()
Method minus() returns new object that differ from the original to the specified time. The class of the new object is the same as the class of the variable on which you run method.
my $new_moment = $moment->minus(
day => 1,
hour => 2,
minute => 3,
second => 4,
);
You can also use negative numbers.
my $two_hours_behind = $moment->minus( hour => -2 );
Here is an example:
say Moment->new(dt=>'2010-01-01 00:00:00')
->minus( day => 1, hour => 2, minute => 3, second => 4 )
->get_dt()
;
# 2009-12-30 21:56:56
get_month_start()
Method get_month_start() returns new object that points to the moment the month starts. The class of the new object is the same as the class of the variable on which you run method.
# 2014-12-01 00:00:00
say Moment->new(dt=>'2014-12-07 11:50:57')->get_month_start()->get_dt();
The time of the new object is always '00:00:00'.
get_month_end()
Method get_month_end() returns new object that points to the moment the month end. The class of the new object is the same as the class of the variable on which you run method.
# 2014-12-31 23:59:59
say Moment->new(dt=>'2014-12-07 11:50:57')->get_month_end()->get_dt();
The time of the new object is always '23:59:59'.
SAMPLE USAGE
Find the last day of the current month (for december 2014 it is 31):
my $day = Moment->now()->get_month_end()->get_day();
Loop for every day in month:
my $start = Moment->now()->get_month_start();
my $end = $start->get_month_end();
my $current = $start;
while ( $current->cmp($end) == -1 ) {
say $current->get_day();
$current = $current->plus( day => 1 );
}
Find out the weekday name for given date (for 2014-01-01 is is wednesday):
my $weekday = Moment->new( dt => '2014-01-01 00:00:00' )->get_weekday_name();
Find out how many seconds in one day (the answer is 86400):
my $moment = Moment->now();
my $seconds_in_a_day = $moment->get_timestamp() - $moment->minus( day => 1 )->get_timestamp();
FAQ
Q: Why there is no parameters 'month' and 'year' in plus() and minus() methods?
A: It is easy to add or substidude second, minute, hour or day from some date. But month and year are different. The number of days in month and year differ from one to anoter. Because of that some touth questions appear. For example what should we get if we add 1 year to the date 2000-02-29? To make this library as simple as possible, I've desided not to implement this feature.
Q: How does this library works with leap seconds?
A: It does not. This library knows nothing about leap seconds.
Q: How should I handle timezones with this module?
A: The best practice to work with time is to work witn time in UTC timezone. This means converting all inputs to UTC timezone and converting it to the desired timezones on output.
You must find out the offset from the UTC timezone and use plus() or minus() methods to create object with UTC time.
For example, if you have time '2014-12-20 18:51:20 +0300' you should create Moment object with the code:
my $m = Moment->new( dt => '2014-12-20 18:51:20' )->minus( hour => 3 );
And if you need to output the time in some special timezone you shlould to the same thing:
say $m->plus( hour => 5, minute => 30 )->get_dt();
Q: Why there is no are no numbers to represent week days?
A: There are several ways to define what is the first day of week. And I don't want to choose one possobility, but implementing all possobilities makes eveything harder. To make this library as simple as possible, I've desided not to implement this feature.
Q: How to serialize this object and deserialize it?
A: There are 2 ways. To use timestamp as the serialised string or to use dt. Timestamp or dt contaings all the needed data to recreate the object with the exact same state.
Serialize timestamp:
my $serialized_timestamp = $moment->get_timestamp();
Restore timestamp:
my $restored_moment = Moment->new( timestamp => $serialized_timestamp );
Serialize dt:
my $serialized_dt = $moment->get_dt();
Restore dt:
my $other_restored_moment = Moment->new( dt => $serialized_dt );
Q: I need my own output format.
A: This is simple. Just write your own class using Moment as the parent and implement method that you need.
Q: Why there is a limitation that this module work only with dates in the range from '1800-01-01 00:00:00' to '2199-12-31 23:59:59'?
A: One of the main ideas behind this libraray is simplicity. Adding this limitations makes the creation and testing of this library simplier. And this limits are enouth for real life problems.
SEE ALSO
DateTime - excellent library. If library Moment does not suit you, please consider using DateTime
https://what-if.xkcd.com/26/ - great explanation of the leap seconds
SOURCE CODE
The source code for this library is hosted on GitHub https://github.com/bessarabov/Moment
BUGS
Please report any bugs or feature requests in GitHub Issues https://github.com/bessarabov/Moment/issues
AUTHOR
Ivan Bessarabov <ivan@bessarabov.ru>
COPYRIGHT AND LICENSE
This software is copyright (c) 2015 by Ivan Bessarabov.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.