RosettaCodeData/Task/Date-manipulation/Pascal/date-manipulation.pas

109 lines
4.4 KiB
ObjectPascal

PROGRAM Date_manipulation;
{$IFDEF FPC}
{$mode objfpc} (*) directive TO be used for defining classes (*)
{$m+} (*) directive TO be used for using constructor (*)
{$LONGSTRINGS ON} (*) aka {H+} = ansistring (*)
{$RANGECHECKS ON} (*) aka {$R+} (*)
{$S+} (*) Stack checking (REQUIRED for exceptions) (*)
{$TYPEDADDRESS ON} (*) aka {$T+} (*)
{$modeswitch exceptions} (*) Explicitly enable exceptions (*)
{$modeswitch advancedrecords}
{$ELSE}
{$APPTYPE CONSOLE}
{$ENDIF}
{$MACRO ON}
{$DEFINE nl := #13#10 }
{$DEFINE tab := #9 }
{$WARNINGS OFF W1033} (*) Stop `data loss from "UnicodeString" to "AnsiString"` messages (*)
{$WARN 6058 OFF} (*) Disable `not inlined` messages (*)
USES
SysUtils,
DateUtils,
StrUtils,
TZDB;
(*)
This program uses the tzdb unit by Alexandru Ciobanu.
Copyright (c) 2010-2020, Alexandru Ciobanu (alex+git@ciobanu.org)
All rights reserved.
This software is provided "as is" without any express or implied warranties.
Please refer to the license for usage terms.
(*)
FUNCTION ParseDateTime(CONST DateTimeStr: string; out TimeZone: string): TDateTime;
VAR
Parts : TStringArray ;
LMonths : TMonthNameArray ;
M, D, Y : Integer ;
TimePart: string ;
BEGIN
Parts := DateTimeStr.Split( [ ' ' ] ) ;
IF Length(Parts) <> 5 THEN
raise Exception.Create( 'Invalid date format' ) ;
(*) Extract Month using system long Month names (*)
LMonths := DefaultFormatSettings.LongMonthNames ;
M := 1 + IndexStr( Parts[ 0 ], LMonths ) ;
D := StrToInt( Parts[ 1 ] ) ;
Y := StrToInt( Parts[ 2 ] ) ;
(*) Handle time with possible space between time and AM/PM (*)
TimePart := Parts[3];
IF Pos('m', Parts[3]) = 0 THEN (*) If 'm' not found, combine parts (*)
TimePart := Parts[3] + Parts[4];
TimeZone := Parts[High(Parts)]; (*) Get timezone abbreviation (*)
Result := EncodeDateTime ( Y, M, D,
HourOf ( StrToTime( TimePart ) ),
MinuteOf ( StrToTime( TimePart ) ), 0, 0 ) ;
END;
CONST
DATESTR = 'mmmm d yyyy h:nnam/pm' ;
VAR
OriginalDate: string;
LocalTime, UTC, NewTime: TDateTime;
NY_TZ, SYD_TZ: TBundledTimeZone;
NY_Abbrev, SYD_Abbrev: string;
BEGIN
OriginalDate := 'March 7 2009 7:30pm EST';
LocalTime := ParseDateTime( OriginalDate, NY_Abbrev ) ;
(*) Initialize timezones (*)
NY_TZ := TBundledTimeZone.GetTimeZone( 'America/New_York' ) ;
SYD_TZ := TBundledTimeZone.GetTimeZone( 'Australia/Sydney' ) ;
UTC := NY_TZ.ToUniversalTime( LocalTime ) ; (*) Convert to UTC (*)
UTC := IncHour( UTC, 12 ) ; (*) Add 12 hours in UTC (*)
NewTime := NY_TZ.ToLocalTime( UTC ) ; (*) back to local time with DST adjustment (*)
NY_Abbrev := NY_TZ.GetAbbreviation( UTC ) ;
(*) Convert TO Sydney time (*)
SYD_Abbrev := SYD_TZ.GetAbbreviation( SYD_TZ.ToLocalTime( UTC ) ) ;
(*) Output results (*)
WriteLn('Original time: ', FormatDateTime( DATESTR, LocalTime ), ' EST' ) ;
WriteLn('+12 hours: ', FormatDateTime( DATESTR, NewTime ), ' ', NY_Abbrev ) ;
WriteLn('Sydney time: ', FormatDateTime( DATESTR, SYD_TZ.ToLocalTime( UTC ) ), ' ', SYD_Abbrev ) ;
END. (*) Of PROGRAM Date_manipulation.pas (*)
(*)