{
    "content": [
        {
            "type": "text",
            "text": "# DateTime::Format::Builder (perldoc)\n\n## NAME\n\nDateTime::Format::Builder - Create DateTime parser classes and objects.\n\n## SYNOPSIS\n\npackage DateTime::Format::Brief;\nuse DateTime::Format::Builder (\nparsers => {\nparsedatetime => [\n{\nregex  => qr/^(\\d{4})(\\d\\d)(\\d\\d)(\\d\\d)(\\d\\d)(\\d\\d)$/,\nparams => [qw( year month day hour minute second )],\n},\n{\nregex  => qr/^(\\d{4})(\\d\\d)(\\d\\d)$/,\nparams => [qw( year month day )],\n},\n],\n}\n);\n\n## DESCRIPTION\n\nDateTime::Format::Builder creates DateTime parsers. Many string formats of dates and times are\nsimple and just require a basic regular expression to extract the relevant information. Builder\nprovides a simple way to do this without writing reams of structural code.\n\n## Sections\n\n- **NAME**\n- **VERSION**\n- **SYNOPSIS**\n- **DESCRIPTION**\n- **TUTORIAL**\n- **ERROR HANDLING AND BAD PARSES**\n- **SINGLE SPECIFICATIONS** (1 subsections)\n- **MULTIPLE SPECIFICATIONS**\n- **EXECUTION FLOW** (2 subsections)\n- **METHODS**\n- **SUBCLASSING**\n- **LONGER EXAMPLES**\n- **THANKS**\n- **SEE ALSO**\n- **SUPPORT**\n- **SOURCE**\n- **DONATIONS**\n- **AUTHORS**\n- **CONTRIBUTORS**\n- **COPYRIGHT AND LICENSE**\n\nUse structuredContent.sections for detailed options, examples, and full documentation.\n"
        }
    ],
    "structuredContent": {
        "command": "DateTime::Format::Builder",
        "section": "",
        "mode": "perldoc",
        "summary": "DateTime::Format::Builder - Create DateTime parser classes and objects.",
        "synopsis": "package DateTime::Format::Brief;\nuse DateTime::Format::Builder (\nparsers => {\nparsedatetime => [\n{\nregex  => qr/^(\\d{4})(\\d\\d)(\\d\\d)(\\d\\d)(\\d\\d)(\\d\\d)$/,\nparams => [qw( year month day hour minute second )],\n},\n{\nregex  => qr/^(\\d{4})(\\d\\d)(\\d\\d)$/,\nparams => [qw( year month day )],\n},\n],\n}\n);",
        "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": "SYNOPSIS",
                "lines": 17,
                "subsections": []
            },
            {
                "name": "DESCRIPTION",
                "lines": 8,
                "subsections": []
            },
            {
                "name": "TUTORIAL",
                "lines": 2,
                "subsections": []
            },
            {
                "name": "ERROR HANDLING AND BAD PARSES",
                "lines": 25,
                "subsections": []
            },
            {
                "name": "SINGLE SPECIFICATIONS",
                "lines": 129,
                "subsections": [
                    {
                        "name": "Callbacks",
                        "lines": 5
                    }
                ]
            },
            {
                "name": "MULTIPLE SPECIFICATIONS",
                "lines": 21,
                "subsections": []
            },
            {
                "name": "EXECUTION FLOW",
                "lines": 3,
                "subsections": [
                    {
                        "name": "For Single Specifications",
                        "lines": 29
                    },
                    {
                        "name": "For Multiple Specifications",
                        "lines": 32
                    }
                ]
            },
            {
                "name": "METHODS",
                "lines": 73,
                "subsections": []
            },
            {
                "name": "SUBCLASSING",
                "lines": 82,
                "subsections": []
            },
            {
                "name": "LONGER EXAMPLES",
                "lines": 4,
                "subsections": []
            },
            {
                "name": "THANKS",
                "lines": 19,
                "subsections": []
            },
            {
                "name": "SEE ALSO",
                "lines": 6,
                "subsections": []
            },
            {
                "name": "SUPPORT",
                "lines": 4,
                "subsections": []
            },
            {
                "name": "SOURCE",
                "lines": 3,
                "subsections": []
            },
            {
                "name": "DONATIONS",
                "lines": 15,
                "subsections": []
            },
            {
                "name": "AUTHORS",
                "lines": 4,
                "subsections": []
            },
            {
                "name": "CONTRIBUTORS",
                "lines": 4,
                "subsections": []
            },
            {
                "name": "COPYRIGHT AND LICENSE",
                "lines": 8,
                "subsections": []
            }
        ],
        "sections": {
            "NAME": {
                "content": "DateTime::Format::Builder - Create DateTime parser classes and objects.\n",
                "subsections": []
            },
            "VERSION": {
                "content": "version 0.83\n",
                "subsections": []
            },
            "SYNOPSIS": {
                "content": "package DateTime::Format::Brief;\n\nuse DateTime::Format::Builder (\nparsers => {\nparsedatetime => [\n{\nregex  => qr/^(\\d{4})(\\d\\d)(\\d\\d)(\\d\\d)(\\d\\d)(\\d\\d)$/,\nparams => [qw( year month day hour minute second )],\n},\n{\nregex  => qr/^(\\d{4})(\\d\\d)(\\d\\d)$/,\nparams => [qw( year month day )],\n},\n],\n}\n);\n",
                "subsections": []
            },
            "DESCRIPTION": {
                "content": "DateTime::Format::Builder creates DateTime parsers. Many string formats of dates and times are\nsimple and just require a basic regular expression to extract the relevant information. Builder\nprovides a simple way to do this without writing reams of structural code.\n\nBuilder provides a number of methods, most of which you'll never need, or at least rarely need.\nThey're provided more for exposing of the module's innards to any subclasses, or for when you\nneed to do something slightly beyond what I expected.\n",
                "subsections": []
            },
            "TUTORIAL": {
                "content": "See DateTime::Format::Builder::Tutorial.\n",
                "subsections": []
            },
            "ERROR HANDLING AND BAD PARSES": {
                "content": "Often, I will speak of \"undef\" being returned, however that's not strictly true.\n\nWhen a simple single specification is given for a method, the method isn't given a single parser\ndirectly. It's given a wrapper that will call \"onfail\" if the single parser returns \"undef\".\nThe single parser must return \"undef\" so that a multiple parser can work nicely and actual\nerrors can be thrown from any of the callbacks.\n\nSimilarly, any multiple parsers will only call \"onfail\" right at the end when it's tried all it\ncould.\n\n\"onfail\" (see later) is defined, by default, to throw an error.\n\nMultiple parser specifications can also specify \"onfail\" with a coderef as an argument in the\noptions block. This will take precedence over the inheritable and overrideable method.\n\nThat said, don't throw real errors from callbacks in multiple parser specifications unless you\nreally want parsing to stop right there and not try any other parsers.\n\nIn summary: calling a method will result in either a \"DateTime\" object being returned or an\nerror being thrown (unless you've overridden \"onfail\" or \"createmethod\", or you've specified a\n\"onfail\" key to a multiple parser specification).\n\nIndividual parsers (be they multiple parsers or single parsers) will return either the\n\"DateTime\" object or \"undef\".\n",
                "subsections": []
            },
            "SINGLE SPECIFICATIONS": {
                "content": "A single specification is a hash ref of instructions on how to create a parser.\n\nThe precise set of keys and values varies according to parser type. There are some common ones\nthough:\n\n*   length\n\nlength is an optional parameter that can be used to specify that this particular *regex* is\nonly applicable to strings of a certain fixed length. This can be used to make parsers more\nefficient. It's strongly recommended that any parser that can use this parameter does.\n\nYou may happily specify the same length twice. The parsers will be tried in order of\nspecification.\n\nYou can also specify multiple lengths by giving it an arrayref of numbers rather than just a\nsingle scalar. If doing so, please keep the number of lengths to a minimum.\n\nIf any specifications without *length*s are given and the particular *length* parser fails,\nthen the non-*length* parsers are tried.\n\nThis parameter is ignored unless the specification is part of a multiple parser\nspecification.\n\n*   label\n\nlabel provides a name for the specification and is passed to some of the callbacks about to\nmentioned.\n\n*   onmatch and onfail\n\nonmatch and onfail are callbacks. Both routines will be called with parameters of:\n\n*   input\n\ninput is the input to the parser (after any preprocessing callbacks).\n\n*   label\n\nlabel is the label of the parser if there is one.\n\n*   self\n\nself is the object on which the method has been invoked (which may just be a class\nname). Naturally, you can then invoke your own methods on it do get information you\nwant.\n\n*   args is an arrayref of any passed arguments, if any. If there were no arguments, then\nthis parameter is not given.\n\nThese routines will be called depending on whether the regex match succeeded or failed.\n\n*   preprocess\n\npreprocess is a callback provided for cleaning up input prior to parsing. It's given a hash\nas arguments with the following keys:\n\n*   input\n\ninput is the datetime string the parser was given (if using multiple specifications and\nan overall *preprocess* then this is the date after it's been through that\npreprocessor).\n\n*   parsed\n\nparsed is the state of parsing so far. Usually empty at this point unless an overall\n*preprocess* was given. Items may be placed in it and will be given to any postprocessor\nand \"DateTime->new\" (unless the postprocessor deletes it).\n\n*   self, args, label\n\nself, args, label as per *onmatch* and *onfail*.\n\nThe return value from the routine is what is given to the *regex*. Note that this is last\ncode stop before the match.\n\nNote: mixing *length* and a *preprocess* that modifies the length of the input string is\nprobably not what you meant to do. You probably meant to use the *multiple parser* variant\nof *preprocess* which is done before any length calculations. This \"single parser\" variant\nof *preprocess* is performed after any length calculations.\n\n*   postprocess\n\npostprocess is the last code stop before \"DateTime->new\" is called. It's given the same\narguments as *preprocess*. This allows it to modify the parsed parameters after the parse\nand before the creation of the object. For example, you might use:\n\n{\nregex       => qr/^(\\d\\d) (\\d\\d) (\\d\\d)$/,\nparams      => [qw( year  month  day   )],\npostprocess => \\&fixyear,\n}\n\nwhere \"fixyear\" is defined as:\n\nsub fixyear {\nmy %args = @;\nmy ( $date, $p ) = @args{qw( input parsed )};\n$p->{year} += $p->{year} > 69 ? 1900 : 2000;\nreturn 1;\n}\n\nThis will cause the two digit years to be corrected according to the cut off. If the year\nwas '69' or lower, then it is made into 2069 (or 2045, or whatever the year was parsed as).\nOtherwise it is assumed to be 19xx. The DateTime::Format::Mail module uses code similar to\nthis (only it allows the cut off to be configured and it doesn't use Builder).\n\nNote: It is very important to return an explicit value from the *postprocess* callback. If\nthe return value is false then the parse is taken to have failed. If the return value is\ntrue, then the parse is taken to have succeeded and \"DateTime->new\" is called.\n\nSee the documentation for the individual parsers for their valid keys.\n\nParsers at the time of writing are:\n\n*   DateTime::Format::Builder::Parser::Regex - provides regular expression based parsing.\n\n*   DateTime::Format::Builder::Parser::Strptime - provides strptime based parsing.\n\nSubroutines / coderefs as specifications.\nA single parser specification can be a coderef. This was added mostly because it could be and\nbecause I knew someone, somewhere, would want to use it.\n\nIf the specification is a reference to a piece of code, be it a subroutine, anonymous, or\nwhatever, then it's passed more or less straight through. The code should return \"undef\" in\nevent of failure (or any false value, but \"undef\" is strongly preferred), or a true value in the\nevent of success (ideally a \"DateTime\" object or some object that has the same interface).\n\nThis all said, I generally wouldn't recommend using this feature unless you have to.\n",
                "subsections": [
                    {
                        "name": "Callbacks",
                        "content": "I mention a number of callbacks in this document.\n\nAny time you see a callback being mentioned, you can, if you like, substitute an arrayref of\ncoderefs rather than having the straight coderef.\n"
                    }
                ]
            },
            "MULTIPLE SPECIFICATIONS": {
                "content": "These are very easily described as an array of single specifications.\n\nNote that if the first element of the array is an arrayref, then you're specifying options.\n\n*   preprocess\n\npreprocess lets you specify a preprocessor that is called before any of the parsers are\ntried. This lets you do things like strip off timezones or any unnecessary data. The most\ncommon use people have for it at present is to get the input date to a particular length so\nthat the *length* is usable (DateTime::Format::ICal would use it to strip off the variable\nlength timezone).\n\nArguments are as for the *single parser* *preprocess* variant with the exception that\n*label* is never given.\n\n*   onfail\n\nonfail should be a reference to a subroutine that is called if the parser fails. If this is\nnot provided, the default action is to call \"DateTime::Format::Builder::onfail\", or the\n\"onfail\" method of the subclass of DTFB that was used to create the parser.\n",
                "subsections": []
            },
            "EXECUTION FLOW": {
                "content": "Builder allows you to plug in a fair few callbacks, which can make following how a parse failed\n(or succeeded unexpectedly) somewhat tricky.\n",
                "subsections": [
                    {
                        "name": "For Single Specifications",
                        "content": "A single specification will do the following:\n\nUser calls parser:\n\nmy $dt = $class->parsedatetime($string);\n\n1   *preprocess* is called. It's given $string and a reference to the parsing workspace hash,\nwhich we'll call $p. At this point, $p is empty. The return value is used as $date for the\nrest of this single parser. Anything put in $p is also used for the rest of this single\nparser.\n\n2   *regex* is applied.\n\n3   If *regex* did not match, then *onfail* is called (and is given $date and also *label* if\nit was defined). Any return value is ignored and the next thing is for the single parser to\nreturn \"undef\".\n\nIf *regex* did match, then *onmatch* is called with the same arguments as would be given to\n*onfail*. The return value is similarly ignored, but we then move to step 4 rather than\nexiting the parser.\n\n4   *postprocess* is called with $date and a filled out $p. The return value is taken as a\nindication of whether the parse was a success or not. If it wasn't a success then the single\nparser will exit at this point, returning undef.\n\n5   \"DateTime->new\" is called and the user is given the resultant \"DateTime\" object.\n\nSee the section on error handling regarding the \"undef\"s mentioned above.\n"
                    },
                    {
                        "name": "For Multiple Specifications",
                        "content": "With multiple specifications:\n\nUser calls parser:\n\nmy $dt = $class->complexparse($string);\n\n1   The overall *preprocess*or is called and is given $string and the hashref $p (identically to\nthe per parser *preprocess* mentioned in the previous flow).\n\nIf the callback modifies $p then a copy of $p is given to each of the individual parsers.\nThis is so parsers won't accidentally pollute each other's workspace.\n\n2   If an appropriate length specific parser is found, then it is called and the single parser\nflow (see the previous section) is followed, and the parser is given a copy of $p and the\nreturn value of the overall *preprocess*or as $date.\n\nIf a \"DateTime\" object was returned so we go straight back to the user.\n\nIf no appropriate parser was found, or the parser returned \"undef\", then we progress to step\n3!\n\n3   Any non-*length* based parsers are tried in the order they were specified.\n\nFor each of those the single specification flow above is performed, and is given a copy of\nthe output from the overall preprocessor.\n\nIf a real \"DateTime\" object is returned then we exit back to the user.\n\nIf no parser could parse, then an error is thrown.\n\nSee the section on error handling regarding the \"undef\"s mentioned above.\n"
                    }
                ]
            },
            "METHODS": {
                "content": "In the general course of things you won't need any of the methods. Life often throws unexpected\nthings at us so the methods are all available for use.\n\nimport\n\"import\" is a wrapper for \"createclass\". If you specify the *class* option (see documentation\nfor \"createclass\") it will be ignored.\n\ncreateclass\nThis method can be used as the runtime equivalent of \"import\". That is, it takes the exact same\nparameters as when one does:\n\nuse DateTime::Format::Builder ( ... )\n\nThat can be (almost) equivalently written as:\n\nuse DateTime::Format::Builder;\nDateTime::Format::Builder->createclass( ... );\n\nThe difference being that the first is done at compile time while the second is done at run\ntime.\n\nIn the tutorial I said there were only two parameters at present. I lied. There are actually\nthree of them.\n\n*   parsers\n\nparsers takes a hashref of methods and their parser specifications. See the\nDateTime::Format::Builder::Tutorial for details.\n\nNote that if you define a subroutine of the same name as one of the methods you define here,\nan error will be thrown.\n\n*   constructor\n\nconstructor determines whether and how to create a \"new\" function in the new class. If given\na true value, a constructor is created. If given a false value, one isn't.\n\nIf given an anonymous sub or a reference to a sub then that is used as \"new\".\n\nThe default is 1 (that is, create a constructor using our default code which simply creates\na hashref and blesses it).\n\nIf your class defines its own \"new\" method it will not be overwritten. If you define your\nown \"new\" and also tell Builder to define one an error will be thrown.\n\n*   verbose\n\nverbose takes a value. If the value is \"undef\", then logging is disabled. If the value is a\nfilehandle then that's where logging will go. If it's a true value, then output will go to\n\"STDERR\".\n\nAlternatively, call $DateTime::Format::Builder::verbose with the relevant value. Whichever\nvalue is given more recently is adhered to.\n\nBe aware that verbosity is a global setting.\n\n*   class\n\nclass is optional and specifies the name of the class in which to create the specified\nmethods.\n\nIf using this method in the guise of \"import\" then this field will cause an error so it is\nonly of use when calling as \"createclass\".\n\n*   version\n\nversion is also optional and specifies the value to give $VERSION in the class. It's\ngenerally not recommended unless you're combining with the *class* option. A\n\"ExtUtils::MakeMaker\" / \"CPAN\" compliant version specification is much better.\n\nIn addition to creating any of the methods it also creates a \"new\" method that can instantiate\n(or clone) objects.\n",
                "subsections": []
            },
            "SUBCLASSING": {
                "content": "In the rest of the documentation I've often lied in order to get some of the ideas across more\neasily. The thing is, this module's very flexible. You can get markedly different behaviour from\nsimply subclassing it and overriding some methods.\n\ncreatemethod\nGiven a parser coderef, returns a coderef that is suitable to be a method.\n\nThe default action is to call \"onfail\" in the event of a non-parse, but you can make it do\nwhatever you want.\n\nonfail\nThis is called in the event of a non-parse (unless you've overridden \"createmethod\" to do\nsomething else.\n\nThe single argument is the input string. The default action is to call \"croak\". Above, where\nI've said parsers or methods throw errors, this is the method that is doing the error throwing.\n\nYou could conceivably override this method to, say, return \"undef\".\n\nUSING BUILDER OBJECTS aka USERS USING BUILDER\nThe methods listed in the METHODS section are all you generally need when creating your own\nclass. Sometimes you may not want a full blown class to parse something just for this one\nprogram. Some methods are provided to make that task easier.\n\nnew\nThe basic constructor. It takes no arguments, merely returns a new \"DateTime::Format::Builder\"\nobject.\n\nmy $parser = DateTime::Format::Builder->new;\n\nIf called as a method on an object (rather than as a class method), then it clones the object.\n\nmy $clone = $parser->new;\n\nclone\nProvided for those who prefer an explicit \"clone\" method rather than using \"new\" as an object\nmethod.\n\nmy $cloneofclone = $clone->clone;\n\nparser\nGiven either a single or multiple parser specification, sets the object to have a parser based\non that specification.\n\n$parser->parser(\nregex  => qr/^ (\\d{4}) (\\d\\d) (\\d\\d) $/x;\nparams => [qw( year    month  day    )],\n);\n\nThe arguments given to \"parser\" are handed directly to \"createparser\". The resultant parser is\npassed to \"setparser\".\n\nIf called as an object method, it returns the object.\n\nIf called as a class method, it creates a new object, sets its parser and returns that object.\n\nsetparser\nSets the parser of the object to the given parser.\n\n$parser->setparser($coderef);\n\nNote: this method does not take specifications. It also does not take anything except coderefs.\nLuckily, coderefs are what most of the other methods produce.\n\nThe method return value is the object itself.\n\ngetparser\nReturns the parser the object is using.\n\nmy $code = $parser->getparser;\n\nparsedatetime\nGiven a string, it calls the parser and returns the \"DateTime\" object that results.\n\nmy $dt = $parser->parsedatetime('1979 07 16');\n\nThe return value, if not a \"DateTime\" object, is whatever the parser wants to return. Generally\nthis means that if the parse failed an error will be thrown.\n\nformatdatetime\nIf you call this function, it will throw an error.\n",
                "subsections": []
            },
            "LONGER EXAMPLES": {
                "content": "Some longer examples are provided in the distribution. These implement some of the common\nparsing DateTime modules using Builder. Each of them are, or were, drop in replacements for the\nmodules at the time of writing them.\n",
                "subsections": []
            },
            "THANKS": {
                "content": "Dave Rolsky (DROLSKY) for kickstarting the DateTime project, writing DateTime::Format::ICal and\nDateTime::Format::MySQL, and some much needed review.\n\nJoshua Hoblitt (JHOBLITT) for the concept, some of the API, impetus for writing the multi-length\ncode (both one length with multiple parsers and single parser with multiple lengths), blame for\nthe Regex custom constructor code, spotting a bug in Dispatch, and more much needed review.\n\nKellan Elliott-McCrea (KELLAN) for even more review, suggestions, DateTime::Format::W3CDTF and\nthe encouragement to rewrite these docs almost 100%!\n\nClaus Färber (CFAERBER) for having me get around to fixing the auto-constructor writing,\nproviding the 'args'/'self' patch, and suggesting the multi-callbacks.\n\nRick Measham (RICKM) for DateTime::Format::Strptime which Builder now supports.\n\nMatthew McGillis for pointing out that \"onfail\" overriding should be simpler.\n\nSimon Cozens (SIMON) for saying it was cool.\n",
                "subsections": []
            },
            "SEE ALSO": {
                "content": "\"datetime@perl.org\" mailing list.\n\nhttp://datetime.perl.org/\n\nperl, DateTime, DateTime::Format::Builder::Tutorial, DateTime::Format::Builder::Parser\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": []
            },
            "DONATIONS": {
                "content": "If you'd like to thank me for the work I've done on this module, please consider making a\n\"donation\" to me via PayPal. I spend a lot of free time creating free software, and would\nappreciate any support you'd care to offer.\n\nPlease note that I am not suggesting that you must do this in order for me to continue working\non this particular software. I will continue to do so, inasmuch as I have in the past, for as\nlong as it interests me.\n\nSimilarly, a donation made in this way will probably not make me work on this software much\nmore, unless I get so many donations that I can consider working on free software full time\n(let's all have a chuckle at that together).\n\nTo donate, log into PayPal and send money to autarch@urth.org, or use the button at\n<https://www.urth.org/fs-donation.html>.\n",
                "subsections": []
            },
            "AUTHORS": {
                "content": "*   Dave Rolsky <autarch@urth.org>\n\n*   Iain Truskett <spoon@cpan.org>\n",
                "subsections": []
            },
            "CONTRIBUTORS": {
                "content": "*   Daisuke Maki <daisuke@endeworks.jp>\n\n*   James Raspass <jraspass@gmail.com>\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": []
            }
        }
    }
}