                        Changes in version 0.6.4                        

  - timeStamp() gains style = "human", which is like "clock" but uses a
    space instead of the "T" separator, e.g. "2019-01-08 12:30:15". Hour
    timestamps always include minutes ("2019-01-08 12:00").
  - html_getTables() no longer passes the deprecated fill argument to
    rvest::html_table(), which now always fills ragged rows with NA. The
    rvest dependency is now rvest (>= 1.0.0).
  - Added tests for ragged HTML tables and for setIfNull() with integer
    input.
  - Documentation updates: clearer timeStamp() description, consistent
    "timezone" wording and a refreshed package website.

                 Changes in version 0.6.3 (2026-09-30)                  

  - timeRange() now actually applies its defaults for unit, ceilingStart
    and ceilingEnd when they are NULL.
  - manageCache() now validates sortBy, maxCacheSize and maxFileAge
    before removing any files. sortBy is now validated with match.arg(),
    so unique abbreviations such as "m" are accepted.
  - Fixed createLocationMask(): with removeZeroZero = TRUE (the default)
    it treated every location where longitude + latitude == 0, e.g. (30,
    -30), as invalid. Now only (0, 0) is removed.
  - Fixed html_getLinks(): with relative = FALSE, protocol-relative
    links (//host/path) are now resolved against the page URL and get
    its scheme, rather than being treated as relative paths.
  - logger.setup() now warns when an existing log file cannot be removed
    before logging starts.
  - Log line timestamps now use lubridate::now(tzone = "UTC"); output
    format is unchanged.
  - loadDataFile() documentation now advises loading data only from
    trusted sources.
  - html_getLinks() and html_getLinkUrls() now stop with an error when
    relative is not a single TRUE or FALSE; previously any other value
    was silently treated as TRUE.
  - Added examples for the API key functions, initializeLogging(), the
    logger.*() functions, logLevels and the check_*() wrappers.
  - Updated the README and vignettes (current stopOnError() behavior,
    WARN.log, current linting output).
  - Added tests for html_getLinks(), html_getLinkNames() and
    html_getLinkUrls().
  - manageCache() now checks whether each file was actually removed.
    Files that cannot be removed generate a warning and are not included
    in the returned count.
  - stopOnError() now builds its message from the supplied try-error
    rather than geterrmessage(), which could return an unrelated, more
    recent error.
  - Fixed a typo in a dateRange() error message.
  - loadDataFile() now stops with a clear message when the .rda file
    contains more than one object; previously it failed with an obscure
    error from get().
  - Timezone validation is now shared by parseDatetime(), timeRange(),
    dateRange(), dateSequence() and timeStamp(), so a timezone that is
    not a single character string produces a clear error everywhere.
  - Added tests for loadDataFile(), html_getTables(), html_getTable(),
    lintFunctionArgs_file(), lintFunctionArgs_dir() and timezone
    validation.
  - showAPIKeys() now masks key values by default. Use mask = FALSE to
    print complete keys.
  - html_getTable() now warns when index < 1 and stops if index is not a
    single integer.
  - Replaced deprecated .data$ tidyselect usage in
    lintFunctionArgs_file().
  - Documented loadDataFile() (file must hold a single object),
    parseDatetime() (error when nothing parses) and logger.setLevel()
    (console only).

                 Changes in version 0.6.2 (2026-05-06)                  

  - Restore but deprecate the algorithm argument from
    createLocationID().

                        Changes in version 0.6.1                        

  - Fixed setIfNull() so that it doesn't ever convert type if the user
    provides a value.
  - Removed the algorithm argument from createLocationID(). Now always
    using geohash.
  - Updated documentation throughout.
  - Added all lubridate functions to timezoneLintRules.
  - Addressed several minor edge cases.

                 Changes in version 0.6.0 (2026-01-12)                  

  - Refactor to use logger rather than futile.logger.
  - Time stamps in log files are now vertically aligned for easier
    scanning.
  - Additional tests of logging functionality.

                 Changes in version 0.5.3 (2024-12-03)                  

  - The loadDataFile() function now includes a priority argument so that
    either dataUrl or dataDir can be prioritized with the other as a
    backup if initial loading of data fails.

                 Changes in version 0.5.2 (2024-02-08)                  

  - initializeLogging() now creates a WARN.log file to complete the
    suite of TRACE, DEBUG, INFO, WARN and ERROR.

                 Changes in version 0.5.1 (2023-11-13)                  

  - Addressed CRAN check error.
  - Added precision argument to createLocationID().

                 Changes in version 0.5.0 (2023-10-28)                  

  - Updated dependencies to R 4.0.0 and rlang 1.1.0.
  - initializeLogging() now properly uses filePrefix argument.
  - The timeStamp() function now defaults to lubridate::now("UTC") when
    no datetime is provided. This supports common use cases such as:

> timeStamp(unit = "hour")
[1] "2023102618"
> timeStamp(style = "clock")
[1] "2023-10-26T18:25:55"

  - Updated imports from futile.logger to avoid error messages like
    this: WARN [2023-08-29 14:06:58] Oops: object 'flog.appender' not
    found
  - Added createLocationMask() to identify invalid locations.
  - createLocationID() now defaults to algorithm = "geohash".
  - createLocationID() now returns the user specified invalidID for
    invalid locations rather than stopping with an error message.

                 Changes in version 0.4.16 (2023-08-29)                 

  - Addressed CRAN package documentation issue.

                 Changes in version 0.4.15 (2023-07-05)                 

  - `parseDatetime() now supports data formats with UTC offset:
    "2018-10-16 12:00:00+00:00".

                 Changes in version 0.4.14 (2023-06-05)                 

  - Added algorithm argument to createLocationID() to select between
    "digest" and "geohash".

The "geohash" algorithm is preferred but the "digest" algorithm is
retained (and the default) because several existing databases use the
"digest" algorithm as a unique identifier.

                 Changes in version 0.4.13 (2022-08-24)                 

  - Updated stopOnError() function documentation and associated
    vignette.

                 Changes in version 0.4.12 (2022-07-20)                 

  - Updated stopOnError() with the following additional arguments:
    prefix, code, maxLength, truncatedLength, call..
  - Corrected documentation for timeStamp().

                       Changes in version 0.4.11                        

  - Changed examples in html_getLinks() and html_getTables() to explain
    any errors with: try({ ...}, silent = FALSE).

                 Changes in version 0.4.10 (2021-11-11)                 

  - New functions for managing API keys: getAPIKey(), setAPIKey(),
    showAPIKeys().
  - Now exporting futile.logger::flog.layout() to avoid downstream
    complaints.
  - Examples for html_getLinks() and html_getTables() now fail
    gracefully.
  - Consolidated the local_~/ directories. (Not part of the R package.)

                 Changes in version 0.4.9 (2021-10-09)                  

  - Updated R dependency to R (>= 3.5.0).
  - Added filePrefix and createDir arguments to initializeLogging().
  - Added location utility functions: validateLonLat(),
    validateLonsLats() and createLocationID().
  - Harmonized error messages to begin with lower case and not include a
    period.
  - Added Zenodo DOI.

                 Changes in version 0.4.8 (2021-08-18)                  

  - Fixed bug in dateRange() when creating single day date ranges.
  - Added "ymdThms" format to timeStamp().
  - Added "msec" unit option to timestamp().
  - Renamed default branch from 'master' to 'main'.

                        Changes in version 0.4.7                        

  - Updated html_getTable() to not disregard the index parameter.

                 Changes in version 0.4.6 (2020-11-13)                  

  - Updated check_~() functions to use devtools::check() manual and
    run_dont_test arguments.

                        Changes in version 0.4.5                        

  - Added header option to html_getLinks() and html_getTables()
    functions.

                 Changes in version 0.4.4 (2020-07-20)                  

  - Added new html_getLinks() and html_getTables() functions.

                 Changes in version 0.4.3 (2020-04-08)                  

  - Now exporting futile.logger::flog.layout() to avoid downstream
    complaints.
  - Updated documentation for check_~() functions.

                 Changes in version 0.4.2 (2020-01-08)                  

  - Fixed error messaging in loadDataFile().
  - Added ceilingStart argument to dateRange() and timeRange().

                        Changes in version 0.4.1                        

  - Fixed improper handling of single day date ranges in dateRange().

                 Changes in version 0.4.0 (2019-11-06)                  

This version address a few issues encountered while using 0.3.11 in
production.

  - New timeStamp() function creates character timestamps useful for
    labeling.
  - New dateSequence() function generates a sequence of POSIXct values
    that align with midnight local time even through the switch to/from
    daylight savings.
  - New loadDataFile() function supports loading data from local
    directories or URLs.
  - Added year-only support to parseDatetime() when parsing julian
    dates.
  - Renamed parsDatetime() argument julian to isJulian.
  - stopIfNull() and setIfNull() now issue stop(...) messages with call.
    = TRUE so that the stack information bubbles up.
  - Now exporting futile.logger::flog.logger() to avoid downstream
    complaints.

                       Changes in version 0.3.11                        

  - Added this package's own date parsing functions to
    timezoneLintrules.

                       Changes in version 0.3.10                        

  - parseDatetime() now supports YYYY and YYYYmm formats.

                 Changes in version 0.3.9 (2019-10-04)                  

  - Added julian argument to parseDatetime() to support Julian day
    formats.

                        Changes in version 0.3.8                        

Added a suite of functions to easily run devtools::check() with
different arguments:

  - check_fastest()

  - check_faster()

  - check_fast()

  - check()

  - check_slow()

  - check_slower()

  - check_slowest()

  - Added more lubridate functions to timezoneLintRules.

                        Changes in version 0.3.7                        

  - Added logger.isInitialized() for programmatic use.
  - logger.setLevel() now guarantees that logger.setup() has been
    called, fixing a bug that generated multiple output messages when
    logger.setLevel() was called before logger.setup().
  - Added more lubridate functions to timezoneLintRules.

                        Changes in version 0.3.6                        

More consistency improvements to dateRange(). When specified, the days
parameter now takes precedence over ceilingEnd when no enddate is
specified.

                 Changes in version 0.3.5 (2019-09-10)                  

Fully self-consistent package using internal functions wherever
possible.

                        Changes in version 0.3.4                        

Various improvements after usage in an operational setting:

  - timezoneLintRules includes more date related functions.
  - Added quiet argument to parseDateTime().
  - timeRange() function now accepts unit and ceilingEnd arguments.
  - dateRange() function now accepts ceilingEnd argument.
  - More unit tests for dates and times.

The ceilingEnd argument addresses the ambiguity of a phrase like:
"August 1-8". With ceilingEnd = FALSE (default) this pharse means
"through the beginning of Aug 8". With ceilingEnd = TRUE it means
"through the end of Aug 8".

                        Changes in version 0.3.3                        

This version adds new convenience functions for dealing with NULL values
in pipeline flow control.

New functions

  - setIfNull()
  - stopIfNull()

Dealing with NULL values

In a lot of the data pipelines we build (web services, packages, etc.),
we need to deal with the possibility of NULL inputs. Setting a default
value or throwing an error are two of the most common ways NUll values
are dealt with. While the code to handle this is straightforward to
write, it is verbose and repetitive. setIfNull() and stopIfNull() are
designed to abstract away boilerplate code, allowing us to focus on more
important things.

                        Changes in version 0.3.2                        

  - Improved documentation for enddate in `dateRange().

                 Changes in version 0.3.1 (2019-08-20)                  

  - Tweak for CRAN.
  - Renamed lintFunctionArgs_directory() to lintFunctionArgs_dir().
  - Added fullPath argument to linting functions.
  - Added date-parsing vignette.

                        Changes in version 0.3.0                        

This version focuses on enhancing the time utility capabilities of
MazamaCoreUtils.

New functions

  - lintFunctionArgs_file()
  - lintFunctionArgs_directory()
  - timeRange()
  - parseDatetime()

Function Argument Linting

In order to ensure that we are working with timezones consistently, the
functions lintFunctionArgs_file() and lintFunctionArgs_directory() were
created to parse R source files and determine if certain functions
contained specific named arguments, based on a set of rules. A set of
rules, timezoneLintRules, was created to check that all functions that
accept a timezone have that argument explicitly fill, avoiding
inconsistent default behavior.

Consolidating Time-Utility functions

PWFSLSmoke::parseDatetime() was moved into MazamaCoreUtils so more
packages can benefit from it without importing the rest of PWFSLSmoke.
Also, timeRange() was created to work as a function analogous to
dateRange(), parsing time ranges instead of finding date ranges.

As part of this consolidation, more unit tests were added to the
package.

                        Changes in version 0.2.1                        

  - Reordered arguments to dateRange().
  - dateRange() no longer provides a default timezone.
  - dateRange() no longer alters POSIXct inputs
  - dateRange() now has stricter argument checking

                 Changes in version 0.2.0 (2019-07-18)                  

  - Moved futile.logger from Depends to Imports.
  - Version bump.

                       Changes in version 0.1.901                       

  - Add linter
  - Add Rproj file
  - Minor style refactor

                       Changes in version 0.1.900                       

  - Added dateRange() function.

                 Changes in version 0.1.3 (2018-12-03)                  

  - Added pkgdown documentation.
  - New vignettes for error-handling and logging.
  - Package now Depends: on futile.logger -- avoids futile.logger not
    found error messages.
  - Additional logging unit tests.

                        Changes in version 0.1.2                        

  - Added maxFileAge parameter to cacheManagement() to help with removal
    of out-of-data products.
  - New dependencies on magrittr and rlang packages.

                 Changes in version 0.1.1 (2018-10-26)                  

  - Minor cleanup and documentation improvements.

                        Changes in version 0.1.0                        

  - Initial functionality.
