Skip to content

Instantly share code, notes, and snippets.

@0racle
Created July 6, 2017 05:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 0racle/3f4a51b2a6aa1c5ee898e24e95b9e704 to your computer and use it in GitHub Desktop.
Save 0racle/3f4a51b2a6aa1c5ee898e24e95b9e704 to your computer and use it in GitHub Desktop.
NativeCall strptime & strftime

I've used this in some personal code... Seems to work fine mostly provided you don't try to get it to parse timezones.

I'm no C programmer. I'm not sure if I've done anything wrong with the NativeCall.

If someone wants steal this and release to the ecosystem, it should probably be added to the already existing POSIX module rather than it's own thing.

use lib 'lib';
use DateTime::Strings;
my $dt = parse-time( '27/02/2015 10:32:04', '%d/%m/%Y %H:%M:%S' );
say $dt.^name;
# DateTime
say $dt;
# 2015-02-27T10:32:04Z
say format-time( $dt, '%d/%m/%Y %H:%M:%S' );
# 27/02/2015 10:32:04
my $now = DateTime.now;
say $now;
# 2017-07-06T15:11:59.931177+10:00
say format-time( $now, '%Y-%m-%d %H:%M:%S' );
# 2017-07-06 15:11:59
unit module DateTime::Strings;
use NativeCall;
constant SIZE = 256;
my class tm is repr('CStruct') {
has int32 $.second;
has int32 $.minute;
has int32 $.hour;
has int32 $.day;
has int32 $.month;
has int32 $.year;
has int32 $.wday;
has int32 $.yday;
has int32 $.isdst;
}
sub strptime(Str, Str, tm) returns Str is native { * }
sub strftime(CArray[int8], size_t, Str, tm) returns size_t is native { * }
sub parse-time (Str \string, Str \format) is export {
my tm $tm .= new;
strptime( string, format, $tm );
my $year = $tm.year
?? $tm.year + 1900
!! DateTime.now.year
;
DateTime.new(
year => $year,
month => ( $tm.month + 1 || 1 ),
day => ( $tm.day || 1 ),
hour => $tm.hour,
minute => $tm.minute,
second => $tm.second,
)
}
sub format-time ( DateTime \dt, Str \format ) is export {
my tm $tm .= new(
second => dt.whole-second,
minute => dt.minute,
hour => dt.hour,
day => dt.day-of-month,
month => dt.month - 1,
year => dt.year - 1900,
wday => dt.day-of-week,
yday => dt.day-of-year,
isdst => 0,
);
my $result := CArray[int8].new;
$result[ SIZE - 1 ] = 0;
my $ret = strftime( $result, SIZE, format, $tm );
$result[ ^SIZE ].map(-> $i {
$i >= 0 ?? $i !! 256 + $i
}).map(&chr).join;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment