#--------------------------------------------------------#
# Module:      Super                                     #
# Package:     Super::System::Datetime                   #
# Version:     1.2                                       #
# File:        Datetime.pm                               #
#--------------------------------------------------------#
# Author:      Sergio Belmar Valenzuela                  #
#              sergio@belmar.name                        #
# Date:        2007-12                                   #
# Update:                                                #
#--------------------------------------------------------#




=DOCUMENTACIÓN

Requerimiento de Librerias
--------------------------

	Módulos o librerías que deben ser llamadas desde el archivo donde es
	utilizada la clase (Externas) y que son requeridas por la misma clase
	(Internas).

	Internas:
		No requiere.

	Externas:
		- Time::Local

Configuración Interna
----------------------------------

	Esta configuración es efectuada en el precente archivo en la sección
	CONFIGURACIÓN PRIVADA y es válida para todos los archivos que utilicen la
	clase Super::System::Datetime.
	Contiene las variables:

	@_MonthsNames
		Arreglo con los nombres de los meses (Enero .. Diciembre).

	@_WeekDaysNames
		Arreglo con los nombres de los días de la semana (Lunes .. Domingo).

	%_SetPropertiesDefaultValues
		Arreglo referenciado que contiene los valores por defecto obtiene el
		objeto cuando es creado sin la especificación de las propiedad como
		parámetro o variable de configuración blanda.
		Este arreglo solo es válido para las llaves:
			- Mode
			- DateFormat
			- TimeFormat
			- DatetimeFormat

Configuración Pública
----------------------------------

	En caso que se utilice este tipo de configuración, debe ser efectuada en 
	un archivo que contenga una prolongación de paquete de esta la clase
	Super::System:::Datetime y solo será valida para los archivos que utilicen
	dicha prolongación de la calse.
	Contiene las variables:

	%SetPropertiesDefaultValues
		Arreglo referenciado con los valores de las propiedades que se cargan
		por defecto al crear un nuevo objeto y no determinar sus propiedades
		mediante SET o pasarlas como argumento al contructor.
		Este arreglo solo es válido para las llaves:
			- Id
			- Mode
			- Year
			- Month
			- MonthDay
			- Hour
			- Minute
			- Second

Propiedades del Objeto
----------------------

	Id (GET/SET)
		Identificador numérico con incremental de un segundo a partir de
		1969-12-31 21:00:00 (Wed Dec 31 21:00:00 1969).

	Mode (GET/SET)
		Modo. Esta propiedad puede adoptar los valores: Local o GMT.

	Year (GET/SET)
		Año.

	Month (GET/SET)
		Mes. (1-12)

	YearDay (GET)
		Días del año. (1-365)

	MonthDay (GET/SET)
		Día del mes. (1-31)

	WeekDay (GET)
		Día de la semana (1-7)

	Hour (GET/SET)
		Hora (0-23)

	Minute (GET/SET)
		Minuto (0-59)

	Second (GET/SET)
		Segundo (0-59)

	DateFormat (GET/SET)
		Formato de la cadena de fecha del objeto.
		El formato repetará las palabras reservadas:
			- yyyy : Año completo.
			- yy   : Últimos dos dígitos del año.
			- mmmm : Nombre completo del mes.
			- mmm  : Promeros tres caracteres del nombre del mes.
			- mm   : Número del mes en formato de dos dígito. 
			- m    : Número del mes en formato de un solo dígito.
			- dd   : Día del mes en formato de dos dígito.
			- d    : Día del mes en formato de un solo dígito.
			- DDDD : Nombre completo del día de la semana.
			- DDD  : Promeros tres caracteres del nombre del día de la semana.
			- DD   : Promeros dos caracteres del nombre del día de la semana.
			- D    : Inicial del nombre del día de la semana.
		Como separación de las palabras tanto reservadas como no, se puede
		utilizar cualquier caracter que no ser de palabra o underscore "_" (\W).

	TimeFormat (GET/SET)
		Formato de la cadena de hora del objeto.
		El formato repetará las palabras reservadas:
			- hh   : Hora en formato de dos dígito.
			- h    : Hora en formato de un solo dígito.
			- MM   : Minuto en formato de dos dígito.
			- M    : Minuto en formato de un solo dígito.
			- ss   : Segundo en formato de dos dígito.
			- s    : Segundo en formato de un solo dígito.
			- $    : Modo horario.
		Como separación de las palabras tanto reservadas como no, se puede
		utilizar cualquier caracter que no ser de palabra o underscore "_" (\W)
		a excepción del signo pesos ($).

	DatetimeFormat (GET/SET)
		Formato de la cadena de fecha-tiempo del objeto.
		El formato repetará las palabras reservadas:
			- yyyy : Año completo.
			- yy   : Últimos dos dígitos del año.
			- mmmm : Nombre completo del mes.
			- mmm  : Promeros tres caracteres del nombre del mes.
			- mm   : Número del mes en formato de dos dígito. 
			- m    : Número del mes en formato de un solo dígito.
			- dd   : Día del mes en formato de dos dígito.
			- d    : Día del mes en formato de un solo dígito.
			- DDDD : Nombre completo del día de la semana.
			- DDD  : Promeros tres caracteres del nombre del día de la semana.
			- DD   : Promeros dos caracteres del nombre del día de la semana.
			- D    : Inicial del nombre del día de la semana.
			- hh   : Hora en formato de dos dígito.
			- h    : Hora en formato de un solo dígito.
			- MM   : Minuto en formato de dos dígito.
			- M    : Minuto en formato de un solo dígito.
			- ss   : Segundo en formato de dos dígito.
			- s    : Segundo en formato de un solo dígito.
			- MODE : Modo horario.
		Como separación de las palabras tanto reservadas como no, se puede
		utilizar cualquier caracter que no ser de palabra o underscore "_" (\W)
		a excepción del signo pesos ($).

Constructor del Objeto
----------------------

	New
		Al crear un nuevo objeto, éste es inicializa con los siguientes
		valores de propiedades:
			- Id       : 0
			- Mode     : $_SetPropertiesDefaultValues{Mode}
			- Year     : 1969
			- Month    : 12
			- YearDay  : 365
			- MonthDay : 31
			- WeekDay  : 3
			- Hour     : 21
			- Minute   : 0
			- Second   : 0

Métodos del Objeto
------------------

	Now
		Carga el objeto con la fecha y hora actual del servidor. Según la
		propiedad modo (Mode) éste va a ser cargado con la hor Local o GMT.

	LocalNow
		Catga el objeto con la fecha y hora actual del servidor en modo Local.

	GmtNow
		Catga el objeto con la fecha y hora actual del servidor en modo GMT.

	GetId
		Carga y retornaObtiene el identificador numérico (Id) en base a las
		demás propiedades del objeto.

	LoadId
		Retorna el objeto previamente actualizadas todas las propiedades en
		base al identificador numérico (Id).

	LoadDatetimeByString
		Retorna el objeto previamente actualizadas todas las propiedades,
		incluido el identificador numérico, luego de pasar como argumento la
		cadena del formato y de la fecha-tiempo.
		El formato repetará las palabras reservadas:
			- yyyy     : Año completo.
			- yy       : Últimos dos dígitos del año.
			- mmmm     : Nombre completo del mes.
			- mmm      : Promeros tres caracteres del nombre del mes.
			- mm       : Número del mes en formato de dos dígito. 
			- m        : Número del mes en formato de un solo dígito.
			- dd       : Día del mes en formato de dos dígito.
			- d        : Día del mes en formato de un solo dígito.
			- hh       : Hora en formato de dos dígito.
			- h        : Hora en formato de un solo dígito.
			- MM       : Minuto en formato de dos dígito.
			- M        : Minuto en formato de un solo dígito.
			- ss       : Segundo en formato de dos dígito.
			- s        : Segundo en formato de un solo dígito.
			- Standard : Standard yyyy-mm-dd hh:MM:ss
			- Default  : Valor de la propuedad 'DatetimeFormat' del objeto.
		Como separación de las palabras tanto reservadas como no, se puede
		utilizar cualquier caracter que no ser de palabra o underscore "_" (\W).
	LoadDatetimeByArray
		Retorna el objeto previamente actualizadas todas las propiedades,
		incluido el identificador numérico, luego de pasar como argumento un
		arreglo con los elementos de la fecha-tiempo en el orden (yyyy,m,d,h,M,s).

	AddYear
		Retorna el objeto previamente actualizadas todas las propiedades, 
		incluido el identificador numérico, luego de haber operado la propiedad
		año (Year) con el valor del entero pasado como argumento.

	AddMonth
		Retorna el objeto previamente actualizadas todas las propiedades, 
		incluido el identificador numérico, luego de haber operado la propiedad
		mes (Month) con el valor del entero pasado como argumento.

	AddDay
		Retorna el objeto previamente actualizadas todas las propiedades, 
		incluido el identificador numérico, luego de haber operado la propiedad
		día (YearDay, MonthDay, WeekDay) con el valor del entero pasado por
		parámetro.

	AddHour
		Retorna el objeto previamente actualizadas todas las propiedades, 
		incluido el identificador numérico, luego de haber operado la propiedad
		hora (Hour) con el valor del entero pasado como argumento.

	AddMinute
		Retorna el objeto previamente actualizadas todas las propiedades, 
		incluido el identificador numérico, luego de haber operado la propiedad
		minuto (Minute) con el valor del entero pasado como argumento.

	AddSecond
		Retorna el objeto previamente actualizadas todas las propiedades, 
		incluido el identificador numérico, luego de haber operado la propiedad
		segundo (Second) con el valor del entero pasado como argumento.

	DateToString
		Retorna la cadena de la fecha del objeto configurada segun el formato
		pasado como argumento.
		El formato repetará las palabras reservadas:
			- yyyy : Año completo.
			- yy   : Últimos dos dígitos del año.
			- mmmm : Nombre completo del mes.
			- mmm  : Promeros tres caracteres del nombre del mes.
			- mm   : Número del mes en formato de dos dígito. 
			- m    : Número del mes en formato de un solo dígito.
			- dd   : Día del mes en formato de dos dígito.
			- d    : Día del mes en formato de un solo dígito.
			- DDDD : Nombre completo del día de la semana.
			- DDD  : Promeros tres caracteres del nombre del día de la semana.
			- DD   : Promeros dos caracteres del nombre del día de la semana.
			- D    : Inicial del nombre del día de la semana.
		Como separación de las palabras tanto reservadas como no, se puede
		utilizar cualquier caracter que no ser de palabra o underscore "_" (\W).

	TimeToString
		Retorna la cadena de la hora del objeto configurada segun el formato
		pasado como argumento.
		El formato repetará las palabras reservadas:
			- hh   : Hora en formato de dos dígito.
			- h    : Hora en formato de un solo dígito.
			- MM   : Minuto en formato de dos dígito.
			- M    : Minuto en formato de un solo dígito.
			- ss   : Segundo en formato de dos dígito.
			- s    : Segundo en formato de un solo dígito.
			- MODE : Modo horario.
		Como separación de las palabras tanto reservadas como no, se puede
		utilizar cualquier caracter que no ser de palabra o underscore "_" (\W)
		a excepción del signo pesos ($).

	ToString
		Retorna la cadena de la fecha-tiempo del objeto configurada segun el
		formato pasado como argumento.
		El formato repetará las palabras reservadas:
			- yyyy : Año completo.
			- yy   : Últimos dos dígitos del año.
			- mmmm : Nombre completo del mes.
			- mmm  : Promeros tres caracteres del nombre del mes.
			- mm   : Número del mes en formato de dos dígito. 
			- m    : Número del mes en formato de un solo dígito.
			- dd   : Día del mes en formato de dos dígito.
			- d    : Día del mes en formato de un solo dígito.
			- DDDD : Nombre completo del día de la semana.
			- DDD  : Promeros tres caracteres del nombre del día de la semana.
			- DD   : Promeros dos caracteres del nombre del día de la semana.
			- D    : Inicial del nombre del día de la semana.
			- hh   : Hora en formato de dos dígito.
			- h    : Hora en formato de un solo dígito.
			- MM   : Minuto en formato de dos dígito.
			- M    : Minuto en formato de un solo dígito.
			- ss   : Segundo en formato de dos dígito.
			- s    : Segundo en formato de un solo dígito.
			- $    : Modo horario.
		Como separación de las palabras tanto reservadas como no, se puede
		utilizar cualquier caracter que no ser de palabra o underscore "_" (\W)
		a excepción del signo pesos ($).

	FirstWeekDayDate
		Retorna un objeto Datetime con la fecha del primer día de la semana.

	LastWeekDayDate
		Retorna un objeto Datetime con la fecha del último día de la semana.

	LastMonthDayDate
		Retorna un objeto Datetime con el último día del mes.

	MonthName
		Retorna la cadena con el nombre completo de la propiedad mes (Month)
		del objeto.

	MonthShortName
		Retorna la cadena con las primeras tres letras del nombre de la
		propiedad mes (Month) del objeto.

	WeekDayName
		Retorna una cadena con el nombre completo de la propiedad día de la
		semana (WeekDay) del objeto.

	WeekDayShortName
		Retorna una cadena con las primeras tres letras del nombre de la
		propiedad día de la semana (WeekDay) del objeto.

Variables Globales
------------------

	%Now
		Arreglo referido con la fecha y hora actual del servidor según el modo
		Local.
		Consta de las llaves, según lo anteriormente descrito:
			- Id
			- Year
			- Month
			- YearDay
			- MonthDay
			- WeekDay
			- Hour
			- Minute
			- Second
			- Date
			- Time
			- Datetime
			- yyyy
			- yy
			- mmmm
			- mmm
			- mm
			- m
			- dd
			- d
			- DDDD
			- DDD
			- DD
			- D
			- hh
			- h
			- MM
			- M
			- ss
			- s

Funciones Públicas
------------------

	GetMonthName
		Retorna el nombre del mes en forato numérico pasado por parámtero
		(1-12).

	GetWeekDayName
		Retorna el nombre de día de semana en forato numérico pasado por
		parámtero (1-7).

Implementación
--------------

	# IMPORTAR LIBRERÍAS

		use Time::Local;
		use Super::System::Datetime;

	# CREAR OBJETO

		my $Datetime = New Super::System::Datetime;

		# ó el equivalente

		my $Datetime = Super::System::Datetime->New();

	# TIEMPO DE SERVIDOR

		# Imprimir la fecha y tiempo de máquina en formato estandar y segín la
		# propiedad modo (Mode) del ojeto.
		print $Datetime->Now->ToString();

		# Imprimir la fecha y tiempo local del servidor en formato estandar,
		# indistintamente del valor de la propiedad modo (Mode) del ojeto.
		print $Datetime->LocalNow->ToString();

		# Imprimir la fecha y tiempo GMT del servidor en formato estandar,
		# indistintamente del valor de la propiedad modo (Mode) del ojeto.
		print $Datetime->GMTNow->ToString();

		# Imprimir la fecha de máquina según el formato pasado como argumento
		# al método.
		print $Datetime->Now->DateToString('d/mmm/yy');

		# Imprimir la fecha y tiempo del servidor en formato estandar, luego de 
		# haber restado 5 minutos.
		print $Datetime->Now->AddMinute(-5)->ToString();

		# Cargar la fecha y hora pasada como argumento y la convierte en un
		# objeto Datetime.
		print "Datetime Load by String 1995-10-22 18:20:56: ".$Datetime->LoadDatetimeByString('yyyy-mm-dd hh:MM:ss', '1995-10-22 18:20:56')->ToString('DDD mmm d hh:MM:ss yyyy MODE')."\n";

=cut




# FECHA Y TIEMPO

package Super::System::Datetime;

	# UNIVERSAL

	$VERSION = '1.0';

	# CONFIGURACIÓN INTERNA

	my @_MonthsNames = qw(
		Enero
		Febrero
		Marzo
		Abril
		Mayo
		Junio
		Julio
		Agosto
		Septiembre
		Octubre
		Noviembre
		Diciembre
	);
	my @_WeekDaysNames = qw(
		Lunes
		Martes
		Miércoles
		Jueves
		Viernes
		Sábado
		Domingo
	);
	my %_SetPropertiesDefaultValues = (
		Mode => 'Local',
		DateFormat => 'yyyy-mm-dd',
		TimeFormat => 'hh:MM:ss',
		DatetimeFormat => 'yyyy-mm-dd hh:MM:ss'
	);

	# CONFIGURACIÓN PÚBLICA

	%SetPropertiesDefaultValues = ();

	# INICIAR VARIABLES PÚBLICA

	&_StartPublicVars();

	# PROPIEDADES

	%SetPropertiesTypes = (
		Id => 'Integer',
		Mode => 'List',
		Year => 'Integer',
		Month => 'List',
		MonthDay => 'List',
		Hour => 'List',
		Minute => 'List',
		Second => 'List',
		DateFormat => 'Scalar',
		TimeFormat => 'Scalar',
		DatetimeFormat => 'Scalar'
	);
	@SetModeValues = qw(
		Local
		GMT
	);
	@SetMonthValues = (1..12);
	@SetMonthDayValues = (1..31);
	@SetHourValues = (0..23);
	@SetMinuteValues = (0..59);
	@SetSecondValues = (0..59);
	sub SetProperty
	{	my $Object = shift;
		my $Name = shift;
		my $Value = shift;
		my $Default = $Object->{$Name};
		my $Property;
		if (defined $Value)
		{	if ($SetPropertiesTypes{$Name} eq 'Integer')
			{	$Property = int($Value);
			}elsif ($SetPropertiesTypes{$Name} eq 'List' && grep(/^$Value$/i, @{"Set".$Name."Values"}))
			{	$Property = $Value;
			}elsif ($SetPropertiesTypes{$Name} eq 'Scalar')
			{	$Property = $Value;
			}
			$Object->{$Name} = $Property if ($Property ne '');
			if (ref($Object) eq 'Super::System::Datetime')
			{	if ($Name eq 'Id')
				{	$Object->LoadId($Value);
				}else
				{	$Object->{Id} = $Object->GetId();
				}
			}
		}elsif (ref($Object) eq 'Super::System::Datetime' && $Name eq 'Id')
		{	$Object->{Id} = $Object->GetId();
		}
	}
	sub Id
	{	my $Object = shift;
		$Object->SetProperty('Id', shift);
		return $Object->{Id};
	}
	sub Mode
	{	my $Object = shift;
		$Object->SetProperty('Mode', shift);
		return $Object->{Mode};
	}
	sub Year
	{	my $Object = shift;
		$Object->SetProperty('Year', shift);
		return $Object->{Year};
	}
	sub Month
	{	my $Object = shift;
		$Object->SetProperty('Month', shift);
		return $Object->{Month};
	}
	sub YearDay
	{	my $Object = shift;
		return $Object->{YearDay};
	}
	sub MonthDay
	{	my $Object = shift;
		$Object->SetProperty('MonthDay', shift);
		return $Object->{MonthDay};
	}
	sub WeekDay
	{	my $Object = shift;
		return $Object->{WeekDay};
	}
	sub Hour
	{	my $Object = shift;
		$Object->SetProperty('Hour', shift);
		return $Object->{Hour};
	}
	sub Minute
	{	my $Object = shift;
		$Object->SetProperty('Minute', shift);
		return $Object->{Minute};
	}
	sub Second
	{	my $Object = shift;
		$Object->SetProperty('Second', shift);
		return $Object->{Second};
	}
	sub DateFormat
	{	my $Object = shift;
		$Object->SetProperty('DateFormat', shift);
		return $Object->{DateFormat};
	}
	sub TimeFormat
	{	my $Object = shift;
		$Object->SetProperty('TimeFormat', shift);
		return $Object->{TimeFormat};
	}
	sub DatetimeFormat
	{	my $Object = shift;
		$Object->SetProperty('DatetimeFormat', shift);
		return $Object->{DatetimeFormat};
	}

	# CONSTRUCTOR

	sub New
	{	my $Object = shift;
		my $Class = ref($Object) || $Object;
		my %Properties = @_;
		my $Properties = {
			Id => 0,
			Mode => $_SetPropertiesDefaultValues{Mode},
			Year => 1969,
			Month => 12,
			YearDay => 365,
			MonthDay => 31,
			WeekDay => 3,
			Hour => 21,
			Minute => 0,
			Second => 0,
			DateFormat => $_SetPropertiesDefaultValues{DateFormat},
			TimeFormat => $_SetPropertiesDefaultValues{TimeFormat},
			DatetimeFormat => $_SetPropertiesDefaultValues{DatetimeFormat}
		};
		foreach my $Property (keys %SetPropertiesTypes)
		{	if (defined $Properties{$Property} && grep(/^$Property$/, keys %Properties))
			{	SetProperty($Properties, $Property, $Properties{$Property});
			}elsif (defined $SetPropertiesDefaultValues{$Property} && grep(/^$Property$/, keys %SetPropertiesDefaultValues))
			{	SetProperty($Properties, $Property, $SetPropertiesDefaultValues{$Property});
			}
		}
		bless $Properties, $Class;
		return $Properties;
	}

	# MÉTODOS

	sub Now
	{	my $Object = shift;
		return $Object->LoadId(time);
	}
	sub LocalNow
	{	my $Object = shift;
		$Object->Mode('Local');
		return $Object->Now();
	}
	sub GMTNow
	{	my $Object = shift;
		$Object->Mode('GMT');
		return $Object->Now();
	}
	sub GetId
	{	my $Object = shift;
		my @Datetime;
		my $Dtm = 0;

		# LEER RPROPIEDADES

		foreach my $Datetime (qw(
			Second
			Minute
			Hour
			MonthDay
			Month
			Year))
		{	push @Datetime, $Object->{$Datetime};
			if ($Datetime eq 'Month')
			{	$Datetime[$Dtm]--;
			}elsif ($Datetime eq 'Year')
			{	$Datetime[$Dtm] -= 1900;
			}
			$Dtm++;
		}

		# CARGAR ID

		if ($Object->{Mode} eq 'Local')
		{	$Object->{Id} = Time::Local::timelocal(@Datetime);
		}elsif ($Object->{Mode} eq 'GMT')
		{	$Object->{Id} = Time::Local::timegm(@Datetime);
		}
		return $Object->{Id};
	}
	sub LoadId
	{	my $Object = shift;
		my $Id = shift;
		my $Dtm = 0;
		my @Datetime;

		# LEER FECHA-HORA DE MÁQUINA

		$Object->{Id} = $Id if ($Id ne '');
		if ($Object->{Mode} eq 'Local')
		{	@Datetime = localtime($Object->{Id});
		}elsif ($Object->{Mode} eq 'GMT')
		{	@Datetime = gmtime($Object->{Id});
		}

		# CARGA RPROPIEDADES

		foreach my $Datetime (qw(
			Second
			Minute
			Hour
			MonthDay
			Month
			Year
			WeekDay
			YearDay))
		{	$Object->{$Datetime} = $Datetime[$Dtm];
			if ($Dtm == 4)
			{	$Object->{$Datetime}++;
			}elsif ($Dtm == 5)
			{	$Object->{$Datetime} += 1900;
			}elsif ($Dtm == 6 && !$Datetime[6])
			{	$Object->{$Datetime} = 7;
			}
			$Dtm++;
		}
		return $Object;
	}
	sub LoadDatetimeByString
	{	my $Object = shift;
		my @Datetime = split /\W/, shift;
		my $Format = shift;
		my @Format = split /\W/, (!length($Format) || $Format eq 'Default' ? $Object->{DatetimeFormat} : $Format eq 'Standard' ? 'yyyy-mm-dd hh:MM:ss' : $Format);
		my $Mth = 0;
		foreach my $Match (@Format)
		{	$Datetime[$Mth] = 0 if (!$Datetime[$Mth]);
			if ($Match eq 'yyyy')
			{	$Object->{Year} = $Datetime[$Mth];
			}elsif ($Match eq 'yy')
			{	$Object->{Year} = '20'.$Datetime[$Mth];
			}elsif ($Match =~ /^(mmmm|mmm)$/)
			{	my $Mnt = 1;
				my $Length = length($Match);
				foreach my $MonthName (@_MonthsNames)
				{	if (lc(substr($MonthName, 0, $Length)) eq lc($Datetime[$Mth]))
					{	$Object->{Month} = $Mnt;
						last;
					}
					$Mnt++;
				}
			}elsif ($Match =~ /^(mm|m)$/)
			{	$Object->{Month} = $Datetime[$Mth];
			}elsif ($Match =~ /^(dd|d)$/)
			{	$Object->{MonthDay} = $Datetime[$Mth];
			}elsif ($Match =~ /^(hh|h)$/)
			{	$Object->{Hour} = $Datetime[$Mth];
			}elsif ($Match =~ /^(MM|M)$/)
			{	$Object->{Minute} = $Datetime[$Mth];
			}elsif ($Match =~ /^(ss|s)$/)
			{	$Object->{Second} = $Datetime[$Mth];
			}elsif ($Match =~ /^MODE$/i)
			{	$Object->Mode($Datetime[$Mth]);
			}
			$Mth++;
		}
		$Object->LoadId($Object->GetId());
		return $Object;
	}
	sub LoadDatetimeByArray
	{	my $Object = shift;
		my @Datetime = shift;
		return $Object->LoadDatetimeByString('yyyy mm dd hh MM ss', join(" ", @Datetime));
	}
	sub AddYear
	{	my $Object = shift;
		my $DeltaYear = int(shift);
		$Object->{Year} += $DeltaYear if ($DeltaYear);
		return $Object->LoadId($Object->GetId());
	}
	sub AddMonth
	{	my $Object = shift;
		my $DeltaMonth = int(shift);
		$Object->{Month} += $DeltaMonth;
		while ($Object->{Month} > 12)
		{	$Object->{Year}++;
			$Object->{Month} -= 12;
		}
		while ($Object->{Month} < 1)
		{	$Object->{Year}--;
			$Object->{Month} += 12;
		}
		return $Object->LoadId($Object->GetId());
	}
	sub AddDay
	{	my $Object = shift;
		return $Object->LoadId($Object->{Id} +(24*60*60)*int(shift));
	}
	sub AddHour
	{	my $Object = shift;
		return $Object->LoadId($Object->{Id} +(60*60)*int(shift));
	}
	sub AddMinute
	{	my $Object = shift;
		return $Object->LoadId($Object->{Id} +(60)*int(shift));
	}
	sub AddSecond
	{	my $Object = shift;
		return $Object->LoadId($Object->{Id} +int(shift));
	}
	sub DateToString
	{	my $Object = shift;
		my $Format = shift;
		my %Replace;
		$Format = !length($Format) || $Format eq 'Default' ? $Object->{DateFormat} : $Format eq 'Standard' ? 'yyyy-mm-dd' : $Format;
		%Replace = (
			'yyyy' => $Object->{Year},
			'yy'   => substr($Object->{Year}, 2, 2),
			'mmmm' => $Object->MonthName(),
			'mmm'  => $Object->MonthShortName(),
			'mm'   => ($Object->{Month} < 10 ? '0'.$Object->{Month} : $Object->{Month}),
			'm'    => $Object->{Month},
			'dd'   => ($Object->{MonthDay} < 10 ? '0'.$Object->{MonthDay} : $Object->{MonthDay}),
			'd'    => $Object->{MonthDay},
			'DDDD' => $Object->WeekDayName(),
			'DDD'  => $Object->WeekDayShortName(),
			'DD'   => substr($_WeekDaysNames[$Object->{WeekDay} -1], 0, 2),
			'D'    => substr($_WeekDaysNames[$Object->{WeekDay} -1], 0, 1)
		);
		foreach my $Key (keys %Replace)
		{	$Format =~ s/(\W|\b|\.|_)$Key(\W|\b|\.|_)/$1$Replace{$Key}$2/;
		}
		return $Format;
	}
	sub TimeToString
	{	my $Object = shift;
		my $Format = shift;
		my %Replace;
		$Format = !length($Format) || $Format eq 'Default' ? $Object->{TimeFormat} : $Format eq 'Standard' ? 'hh:MM:ss' : $Format;
		%Replace = (
			'hh'   => ($Object->{Hour} < 10 ? '0'.$Object->{Hour} : $Object->{Hour}),
			'h'    => $Object->{Hour},
			'MM'   => ($Object->{Minute} < 10 ? '0'.$Object->{Minute} : $Object->{Minute}),
			'M'    => $Object->{Minute},
			'ss'   => ($Object->{Second} < 10 ? '0'.$Object->{Second} : $Object->{Second}),
			's'    => $Object->{Second},
			'MODE' => $Object->{Mode}
		);
		foreach my $Key (keys %Replace)
		{	$Format =~ s/(\W|\b|\.|_)$Key(\W|\b|\.|_)/$1$Replace{$Key}$2/;
		}
		return $Format;
	}
	sub ToString
	{	my $Object = shift;
		my $Format = shift;
		my $Output = $Format;
		$Output = !length($Format) || $Format eq 'Default' ? $Object->{DatetimeFormat} : $Format eq 'Standard' ? 'yyyy-mm-dd hh:MM:ss' : $Format eq 'LongTime' ? 'yyyy-mm-dd T hh:MM:ss' : $Format;
		$Output = $Object->DateToString($Output);
		$Output = $Object->TimeToString($Output);
		$Output =~ s/\s//g if ($Format eq 'LongTime');
		return $Output;
	}
	sub FirstWeekDayDate
	{	my $Object = shift;
		my $Datetime = $Object;
		return $Datetime->AddDay(1 -$Datetime->WeekDay());
	}
	sub LastWeekDayDate
	{	my $Object = shift;
		my $Datetime = $Object->FirstWeekDayDate();
		return $Datetime->AddDay(6);
	}
	sub LastMonthDayDate
	{	my $Object = shift;
		my $Date = New Super::System::Datetime(
			Year => $Object->{Year},
			Month => $Object->{Month},
			MonthDay => 1,
			Hour => 0
		);
		return $Date->AddMonth(+1)->AddDay(-1);
	}
	sub LastMonthDay
	{	my $Object = shift;
		return $Object->LastMonthDayDate()->{MonthDay};
	}
	sub MonthName
	{	my $Object = shift;
		return $_MonthsNames[$Object->Month -1];
	}
	sub MonthShortName
	{	my $Object = shift;
		return substr($Object->MonthName(), 0, 3);
	}
	sub WeekDayName
	{	my $Object = shift;
		return $_WeekDaysNames[$Object->WeekDay -1];
	}
	sub WeekDayShortName
	{	my $Object = shift;
		return substr($Object->WeekDayName(), 0, 3);
	}

	# FUNCIONES PRIVADAS

	sub _StartPublicVars
	{	my $Datetime = New Super::System::Datetime;
		$Datetime->Now();
		foreach my $Property (qw(
			Id
			Second
			Minute
			Hour
			WeekDay
			MonthDay
			YearDay
			Month
			Year))
		{	$Now{$Property} = $Datetime->{$Property};
		}
		foreach my $Match (qw(
			yyyy
			yy
			mmmm
			mmm
			mm
			m
			dd
			d
			DDDD
			DDD
			DD
			D
			hh
			h
			MM
			M
			ss
			s
			MODE
			Standard))
		{	$Now{$Match} = $Datetime->ToString($Match);
		}
	}

	# FUNCIONES PÚBLICAS

	sub GetMonthName
	{	my $Month = shift;
		return $_MonthsNames[$Month -1];
	}
	sub GetMonthShortName
	{	my $Month = shift;
		return substr($_MonthsNames[$Month -1], 0, 3);
	}
	sub GetWeekDayName
	{	my $Day = shift;
		return $_WeekDaysNames[$Day -1];
	}
	sub GetWeekDayShortName
	{	my $Day = shift;
		return substr($_WeekDaysNames[$Day -1], 0, 3);
	}

1;

__END__