{
    "content": [
        {
            "type": "text",
            "text": "# DateTime::Format::Builder::Tutorial (perldoc)\n\n## NAME\n\nDateTime::Format::Builder::Tutorial - Quick class on using Builder\n\n## Sections\n\n- **NAME**\n- **VERSION**\n- **CREATING A CLASS**\n- **SEE ALSO**\n- **SUPPORT**\n- **SOURCE**\n- **AUTHORS**\n- **COPYRIGHT AND LICENSE**\n\nUse structuredContent.sections for detailed options, examples, and full documentation.\n"
        }
    ],
    "structuredContent": {
        "command": "DateTime::Format::Builder::Tutorial",
        "section": "",
        "mode": "perldoc",
        "summary": "DateTime::Format::Builder::Tutorial - Quick class on using Builder",
        "synopsis": null,
        "tldr_summary": null,
        "tldr_examples": [],
        "tldr_source": null,
        "flags": [],
        "examples": [],
        "see_also": [],
        "section_outline": [
            {
                "name": "NAME",
                "lines": 2,
                "subsections": []
            },
            {
                "name": "VERSION",
                "lines": 2,
                "subsections": []
            },
            {
                "name": "CREATING A CLASS",
                "lines": 236,
                "subsections": []
            },
            {
                "name": "SEE ALSO",
                "lines": 6,
                "subsections": []
            },
            {
                "name": "SUPPORT",
                "lines": 4,
                "subsections": []
            },
            {
                "name": "SOURCE",
                "lines": 3,
                "subsections": []
            },
            {
                "name": "AUTHORS",
                "lines": 4,
                "subsections": []
            },
            {
                "name": "COPYRIGHT AND LICENSE",
                "lines": 8,
                "subsections": []
            }
        ],
        "sections": {
            "NAME": {
                "content": "DateTime::Format::Builder::Tutorial - Quick class on using Builder\n",
                "subsections": []
            },
            "VERSION": {
                "content": "version 0.83\n",
                "subsections": []
            },
            "CREATING A CLASS": {
                "content": "As most people who are writing modules know, you start a package with a package declaration and\nsome indication of module version:\n\npackage DateTime::Format::ICal; our $VERSION = '0.04';\n\nAfter that, you call Builder with some options. There are only a few (detailed later). Right\nnow, we're only interested in *parsers*.\n\nuse DateTime::Format::Builder ( parsers => {...} );\n\nThe *parsers* option takes a reference to a hash of method names and specifications:\n\nparsers => {\nparsedatetime => ... ,\nparsedatetimewithtimezone => ... ,\n...\n}\n\nBuilder will create methods in your class, each method being a parser that follows the given\nspecifications. It is strongly recommended that one method is called *parsedatetime*, be it a\nBuilder created method or one of your own.\n\nIn addition to creating any of the parser methods it also creates a \"new\" method that can\ninstantiate (or clone) objects of this class. This behaviour can be modified with the\n*constructor* option, but we don't need to know that yet.\n\nEach value corresponding to a method name in the parsers list is either a single specification,\nor a list of specifications. We'll start with the simple case.\n\nparsebriefdate => { params => [qw( year month day )], regex =>\nqr/^(\\d\\d\\d\\d)(\\d\\d)(\\d\\d)$/, },\n\nThis will result in a method named *parsebriefdate* which will take strings in the form\n20040716 and return DateTime objects representing that date. A user of the class might write:\n\nuse DateTime::Format::ICal;\nmy $date = '19790716';\nmy $dt   = DateTime::Format::ICal->parsebriefdate($date);\nprint \"My birth month is \", $dt->monthname, \"\\n\";\n\nThe \"regex\" is applied to the input string, and if it matches, then $1, $2, ... are mapped to\nthe *params* given and handed to \"DateTime->new\". Essentially:\n\nmy $rv = DateTime->new( year => $1, month => $2, day => $3 );\n\nThere are more complicated things one can do within a single specification, but we'll cover\nthose later.\n\nOften, you'll want a method to be able to take one string, and run it against multiple parser\nspecifications. It would be very irritating if the user had to work out what format the datetime\nstring was in and then which method was most appropriate.\n\nSo, Builder lets you specify multiple specifications:\n\nparsedatetime => [\n{\nparams => [qw( year month day hour minute second )],\nregex  => qr/^(\\d\\d\\d\\d)(\\d\\d)(\\d\\d)T(\\d\\d)(\\d\\d)(\\d\\d)$/,\n},\n{\nparams => [qw( year month day hour minute )],\nregex  => qr/^(\\d\\d\\d\\d)(\\d\\d)(\\d\\d)T(\\d\\d)(\\d\\d)$/,\n},\n{\nparams => [qw( year month day hour )],\nregex  => qr/^(\\d\\d\\d\\d)(\\d\\d)(\\d\\d)T(\\d\\d)$/,\n},\n{\nparams => [qw( year month day )],\nregex  => qr/^(\\d\\d\\d\\d)(\\d\\d)(\\d\\d)$/,\n},\n],\n\nIt's an arrayref of specifications. A parser will be created that will try each of these\nspecifications sequentially, in the order you specified.\n\nThere's a flaw with this though. In this example, we're building a parser for ICal datetimes.\nOne can place a timezone id at the start of an ICal datetime. You might extract such an id with\nthe following code:\n\nif ( $date =~ s/^TZID=([^:]+):// ) {\n$timezone = $1;\n}\n\n# Z at end means UTC\nelsif ( $date =~ s/Z$// ) {\n$timezone = 'UTC';\n}\nelse {\n$timezone = 'floating';\n}\n\n$date would end up without the id, and $timezone would contain something appropriate to give to\nDateTime's *settimezone* method, or *timezone* argument.\n\nBut how to get this scrap of code into your parser? You might be tempted to call the parser\nsomething else and build a small wrapper. There's no need though because an option is provided\nfor preprocessing dates:\n\nparsedatetime => [\n[ preprocess => \\&parsetz ],    # Only changed line!\n{\nparams => [qw( year month day hour minute second )],\nregex  => qr/^(\\d\\d\\d\\d)(\\d\\d)(\\d\\d)T(\\d\\d)(\\d\\d)(\\d\\d)$/,\n},\n{\nparams => [qw( year month day hour minute )],\nregex  => qr/^(\\d\\d\\d\\d)(\\d\\d)(\\d\\d)T(\\d\\d)(\\d\\d)$/,\n},\n{\nparams => [qw( year month day hour )],\nregex  => qr/^(\\d\\d\\d\\d)(\\d\\d)(\\d\\d)T(\\d\\d)$/,\n},\n{\nparams => [qw( year month day )],\nregex  => qr/^(\\d\\d\\d\\d)(\\d\\d)(\\d\\d)$/,\n},\n],\n\nIt will necessitate *parsetz* to be written, and that routine looks like this:\n\nsub parsetz {\nmy %args = @;\nmy ( $date, $p ) = @args{qw( input parsed )};\nif ( $date =~ s/^TZID=([^:]+):// ) {\n$p->{timezone} = $1;\n}\n\n# Z at end means UTC\nelsif ( $date =~ s/Z$// ) {\n$p->{timezone} = 'UTC';\n}\nelse {\n$p->{timezone} = 'floating';\n}\nreturn $date;\n}\n\nOn input it is given a hash containing two items: the input date and a hashref that will be used\nin the parsing. The return value from the routine is what the parser specifications will run\nagainst, and anything in the *parsed* hash ($p in the example) will be put in the call to\n\"DateTime->new(...)\".\n\nSo, we now have a happily working ICal parser. It parses the assorted formats, and can also\nhandle timezones. Is there anything else it needs to do? No. But we can make it work more\nefficiently.\n\nAt present, the specifications are tested sequentially. However, each one applies to strings of\nparticular lengths. Thus we could be efficient and have the parser only test the given strings\nagainst a parser that handles that string length. Again, Builder makes it easy:\n\nparsedatetime => [\n[ preprocess => \\&parsetz ],\n{\nlength => 15,    # We handle strings of exactly 15 chars\nparams => [qw( year month day hour minute second )],\nregex  => qr/^(\\d\\d\\d\\d)(\\d\\d)(\\d\\d)T(\\d\\d)(\\d\\d)(\\d\\d)$/,\n},\n{\nlength => 13,                                # exactly 13 chars...\nparams => [qw( year month day hour minute )],\nregex => qr/^(\\d\\d\\d\\d)(\\d\\d)(\\d\\d)T(\\d\\d)(\\d\\d)$/,\n},\n{\nlength => 11,                                    # 11..\nparams => [qw( year month day hour )],\nregex  => qr/^(\\d\\d\\d\\d)(\\d\\d)(\\d\\d)T(\\d\\d)$/,\n},\n{\nlength => 8,                                     # yes.\nparams => [qw( year month day )],\nregex  => qr/^(\\d\\d\\d\\d)(\\d\\d)(\\d\\d)$/,\n},\n],\n\nNow the created parser will create a parser that only runs specifications against appropriate\nstrings.\n\nSo our complete code looks like:\n\npackage DateTime::Format::ICal;\nuse strict;\nour $VERSION = '0.04';\n\nuse DateTime::Format::Builder (\nparsers => {\nparsedatetime => [\n[ preprocess => \\&parsetz ],\n{\nlength => 15,\nparams => [qw( year month day hour minute second )],\nregex  => qr/^(\\d\\d\\d\\d)(\\d\\d)(\\d\\d)T(\\d\\d)(\\d\\d)(\\d\\d)$/,\n},\n{\nlength => 13,\nparams => [qw( year month day hour minute )],\nregex  => qr/^(\\d\\d\\d\\d)(\\d\\d)(\\d\\d)T(\\d\\d)(\\d\\d)$/,\n},\n{\nlength => 11,\nparams => [qw( year month day hour )],\nregex  => qr/^(\\d\\d\\d\\d)(\\d\\d)(\\d\\d)T(\\d\\d)$/,\n},\n{\nlength => 8,\nparams => [qw( year month day )],\nregex  => qr/^(\\d\\d\\d\\d)(\\d\\d)(\\d\\d)$/,\n},\n],\n},\n);\n\nsub parsetz {\nmy %args = @;\nmy ( $date, $p ) = @args{qw( input parsed )};\nif ( $date =~ s/^TZID=([^:]+):// ) {\n$p->{timezone} = $1;\n}\n\n# Z at end means UTC\nelsif ( $date =~ s/Z$// ) {\n$p->{timezone} = 'UTC';\n}\nelse {\n$p->{timezone} = 'floating';\n}\nreturn $date;\n}\n\n1;\n\nAnd that's an ICal parser. The actual DateTime::Format::ICal module also includes formatting\nmethods and parsing for durations, but Builder doesn't support those yet. A drop in replacement\n(at the time of writing the replacement) can be found in the examples directory of the Builder\ndistribution, along with similar variants of other common modules.\n",
                "subsections": []
            },
            "SEE ALSO": {
                "content": "\"datetime@perl.org\" mailing list.\n\nhttp://datetime.perl.org/\n\nperl, DateTime, DateTime::Format::Builder\n",
                "subsections": []
            },
            "SUPPORT": {
                "content": "Bugs may be submitted at <https://github.com/houseabsolute/DateTime-Format-Builder/issues>.\n\nI am also usually active on IRC as 'autarch' on \"irc://irc.perl.org\".\n",
                "subsections": []
            },
            "SOURCE": {
                "content": "The source code repository for DateTime-Format-Builder can be found at\n<https://github.com/houseabsolute/DateTime-Format-Builder>.\n",
                "subsections": []
            },
            "AUTHORS": {
                "content": "*   Dave Rolsky <autarch@urth.org>\n\n*   Iain Truskett <spoon@cpan.org>\n",
                "subsections": []
            },
            "COPYRIGHT AND LICENSE": {
                "content": "This software is Copyright (c) 2020 by Dave Rolsky.\n\nThis is free software, licensed under:\n\nThe Artistic License 2.0 (GPL Compatible)\n\nThe full text of the license can be found in the LICENSE file included with this distribution.\n",
                "subsections": []
            }
        }
    }
}