Verifying a [DATETIME] format string is valid or not with Confirm-DateTimeFormatPattern

Early this evening I sent this tweet out regarding a #PowerShell Function I wrote called Confirm-DateTimeFormatPattern and Dan Franciscus (@dan_franciscus) recommend that I should blog about it, so here it goes!

To elaborate on that tweet, this Function spawned from a larger initiative that I am working on for a presentation I’m giving at PowerShell Summit 2018 in April.  That presentation will be about a PowerShell Module I have built called PSLogging, which is a logging framework built using PowerShell Classes.

One of the items on my to-do list, which always seems to grow and not shrink, is to add a configuration component.  This configuration component would allow someone to create a config.json or config.yml file that would be referenced when logging within their application/script/function/etc.  Here is a quick example of what the configuration may (work in-progress) look like:

Within this configuration file I would allow someone to specify the “log level” and all the available formatting options.  As you can see in the image above, one such configuration option is that ability to specify the datetime format, a filename, encoding, etc.  But the point of this post is specifically about the datetime format option.

I needed (wanted) a way to identify if the provided format string in the datetime configuration option is an actual valid [DATETIME] format string value.  If you are not familiar with this concept, then please see the below example when using the Get-Date Cmdlet:

PS /Users/josh.rickard> Get-Date -Format "yyyy-MM-dd HH:mm:ss"
2018-02-11 22:43:05

To further explain, I will show you a snippet of PowerShell code and the corresponding Class that does exactly what I described above and it may shed some light on the “why”. Imagine you have a JSON configuration file, but it has multiple options available and only certain options are “mandatory”. You would first need to load the content from that JSON file and then convert it using the ConvertFrom-Json Cmdlet. The next step is that you would need to iterate through the configuration and identify (and verify) each piece of configuration before you rely on it, right? Here’s an example of just that:

$JsonConfigurationFile = 'C:\_Github\PSLogging\PSLogging\config\logging.json'
$JsonConfig = Get-Content -Path $JsonConfigurationFile | ConvertFrom-Json
$FormatObject = @()

foreach($output in $JsonConfig.outputs)
{
    if ($output.PSObject.Properties.Name -eq 'console')
    {
        if ([DateTimeValidation]::validateDateTimePatterns($output.console.datetime))
        {
            [ConsoleConfiguration]::setConsoleConfiguration($output.console.level, $output.console.datetime)
        }
        else
        {
            Write-Error -Message 'Error!  Could not Validate Date Time Patterns!'
            Throw
        }
    }
}

As you can see, we loop through the first time and identify if the console setting was set, if it was then we would need to check and see if the passed in [datetime] format string is correct, if it is then set our console configuration (if you’re following along, let me tell you there are other forms of validation this is just an example). 🙂

Now, to show you the [DateTimeValidation] Class that is doing all the magic. Additionally, I have a ConsoleConfiguration Class and a LogLevel Enum but we won’t get into the details of those at this time:

enum LogLevel
{
    INFO
    DEBUG
    SUCCESS
    WARNING
    ERROR
}

Class DateTimeValidation
{
    static [string] $DateTimePattern

    static [bool] validateDateTimePatterns([string]$Pattern)
    {
        $TimePatterns = [System.Globalization.DateTimeFormatInfo]::CurrentInfo

        foreach ($item in $TimePatterns.GetAllDateTimePatterns())
        {
            if ($Pattern -eq $item)
            {
                [DateTimeValidation]::DateTimePattern = $Pattern
                return $true
            }
        }
        return $false
    }
}

# Define a class
class ConsoleConfiguration
{
   static [LogLevel] $LogLevel
   static [DateTimeValidation] $DateTimeFormat

   # Static method
   static [void] setConsoleConfiguration([LogLevel]$Level, [string]$DateTimeFormat)
   {
        $DateTimeFormat
        [ConsoleConfiguration]::LogLevel = $Level
        [ConsoleConfiguration]::DateTimeFormat = $DateTimeFormat
   }
}

To briefly explain, we call the [DateTimeValidation] Class from within our If statement above. This call then validates that our passed in [string] format is valid (or not) based on the current Culture/Globalization settings. Once the provided string data has been validated, then we can proceed to add it to our [ConsoleConfiguration] Class. The great thing about this class is that I can just reuse it, over and over and over.

Now, let’s get back to the actual function and not all this Class non-sense. I ported over the logic from a Class in my PSLogging Module because I thought it would be useful to validate this type of input. In #PowerShell, especially Advanced Functions, we learn/preach/teach that we should always validate our inputs and ensure our outputs are what the user expects – this is crucial in any language. If you are familiar with Parameter Validation on PowerShell Functions then this should come at no surprise to you. We should ALWAYS validate our data!

This function is no different. You may not have a use case for it now, and this is NOT revolutionary at all, but there may come a time when you need to validate those pesky string formatting rules and I hope this function helps out.

You can find the GIST here: https://gist.github.com/MSAdministrator/b2c3ace163c4fbf76069503528de6cf1

And the full code here for the lazy:

.Synopsis
    Confirm if a date time format pattern is valid or not 
.DESCRIPTION
    Confirm if a date time format pattern is valid or not     
    based on the current culture on the machine that this function     
    is being ran on 
.EXAMPLE 1 
    PS C:\> Confirm-DateTimeFormatPattern -Format "yyyy-MM-dd HH:mm:ss"

    Format              Valid
    ------              -----
    yyyy-MM-dd HH:mm:ss  True

.EXAMPLE 2
    PS C:\> Confirm-DateTimeFormatPattern -Format "yyyy-MM-dd HH:mm:ss", "xxx-MM/dd/yy"

    Format              Valid
    ------              -----
    yyyy-MM-dd HH:mm:ss  True
    xxx-MM/dd/yy        False

.EXAMPLE 3
    PS C:\> "yyyy-MM-dd HH:mm:ss", "xxx-MM/dd/yy", "MMMM d", "yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffffffK" | Confirm-DateTimeFormatPattern

    Format                                 Valid
    ------                                 -----
    yyyy-MM-dd HH:mm:ss                     True
    xxx-MM/dd/yy                           False
    MMMM d                                  True
    yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffffffK  True
function Confirm-DateTimeFormatPattern
{
    [CmdletBinding()]
    [Alias()]
    [OutputType([PSCustomObject])]
    Param
    (
        # Param1 help description
        [Parameter(Mandatory=$true,
                   ValueFromPipeline=$true,
                   ValueFromPipelineByPropertyName=$true,
                   Position=0)]
        [string[]]$Format
    )

    Begin
    {
        $CultureObject = ([System.Globalization.DateTimeFormatInfo]::CurrentInfo).GetAllDateTimePatterns()
    }
    Process
    {
        foreach ($item in $Format)
        {
            if ($CultureObject -contains $item)
            {
                $props = [PSCustomObject]@{
                    'Format' = $item
                    'Valid'  = $true
                }
                Write-Output $props
            }
            else
            {
                $props = [PSCustomObject]@{
                    'Format' = $item
                    'Valid'  = $false
                }
                Write-Output $props
            }
        }
    }
    End
    {
        # Intentionally Left Blank
    }
}
Advertisements

PowerShell ISE Snippets

Whether you are a pro with PowerShell or a beginner, PowerShell ISE snippets can speed up your scripting and assist when you are unsure of formatting.

Most IT professionals who work with PowerShell to build tools, scripts, or modules use the built-in PowerShell ISE (Integrated Scripting Environment) to build and debug their code.

Read More

Design Before Coding: Kanban

The first post in this three-part series focused on gathering requirements before spending time coding.  While it is not necessary, I recommend that everyone read part 1 (Gathering Requirements).  Understanding and having clear “User Stories” outlining the intended purpose of a tool is crucial, especially as we move towards building our new tool.

Once our “User Stories” have been defined and agreed upon by all stakeholders, we then need to begin breaking them down into tasks.  There are many different methodologies that allow us to track these different tasks. Part 2 of this three-part series will focus on one of them; Kanban.

I use Kanban daily, both personally and professionally.  If you want to understand the principles of Kanban, then I recommend that you start with this Wikipedia page. No matter what methodology or process you use, having a consistent and repeatable utility is a must.

This post will go over using Kanban both digitally and manually, but first you must understand the general purpose of Kanban.  Tracking our work can be difficult, especially with the use of E-mail, Slack, Skype, Teams, Yammer, HipChat, etc. etc.  The constant communication that is available to us is overwhelming, but having a central location that you can organize your “To-Do’s” or tasks is necessary.  Not for our management or organizations tracking purposes, it is so that we can track exactly what we need to do next.

factory-35081_1280

The theory of Kanban is to visually identify items that need to be worked on. Kanban allows you to understand what tasks need to be worked on, which ones are in-progress, and which ones are complete.  Using this information, we begin to identify any blockers or obstacles that may need to be fixed so that an item/task can move from “To Do” to “Done”.  This principle helps us identify our WIP (Work in Progress) so that the flow between “gates” or “hand-off points” is as smooth and controlled as possible.  Think of this like an assembly line:

Let’s say we have two workers in an assembly line.  The first person’s job is to paint a car door handle, the second person’s job is to install that door handle on a new car.  If the first person can paint 5 handles in 10 minutes, but the second person takes 10 minutes to install the handle; we have a problem.  This means that we either need to increase staff that install car door handles or maybe the same person should do both.

Understanding these blockers will help us identify gaps in our processes, or the lack of labor to accomplish our goals.  Visually displaying this information on a Kanban board is much easier to understand than a bunch of tasks lists or “tickets”.

There are many tools available for a digital Kanban board.  I have listed a few below that are both free and paid.  In my professional life, I use Jira’s Kanban feature.  In my personal life, I use both a whiteboard with post-it notes and built-in features of GitHub Projects (example):

If you just do a quick google search for “free Kanban tools” or go to GitHub.com and search for “Kanban” you will find many open source projects that you can host yourself.  If you don’t want to host it yourself, then check out DigitalOcean.com.  If you think a digital tool would work for you, you can even use Outlook (here or here) or Gmail to manage your tasks in the Kanban style.

I’m not sure about you, but I personally carry a leather-bound notebook (with DoanePaper) with me wherever I go.  Whether at work, out with friends, going to bed, etc., I always have my notebook.  In my opinion a digital tool is great, but I’m faster at writing things down on paper than I am opening an app.  Plus, I always have it with me.

Simple-kanban-board-

Another option or addition is by using a whiteboard in your home or work office.  The first thing you do is draw some columns.  Typically, you have three different columns: To-Do, In-Progress, and Done.  Starting out you will have everything in your To-Do column.  As you begin a new task you move that sticky-note to the In-Progress column.  If that item gets blocked or cannot be completed, you should move it back to the To-Do column.  You should only have a few items In-Progress (ideally, you would only have one).  Once you have completed that task, you move it to the Done column.

That’s it! Kanban allows you to visually see tasks and progress you are making on your projects.  The manual process is great for a single person or a team that is in close quarters.  If you’re spread out or in a cubicle this may not work as well.  This is where having a platform like Jira or Trello really shines.  Especially for teams that are global or in different locations.

Kanban is powerful, yet extremely simple. Using a tool to manage your tasks so that you understand exactly what you, your team, and others are working on reduces potential re-work while also making sure that all tasks for a project are complete (and on-time).  The third post in this series I will take the concepts of both post one and two, and we will begin to breakdown our User Stories onto our Kanban board.  Remember, we have not started coding yet.  Next, we will design how our stakeholders may use our new tool.  Understanding this, will speed up our development time and reduce re-work.