dcmtime

package
v0.0.0-...-e92d98b Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 25, 2024 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package dcmtime contains functions and data types for converting DICOM date and time values to native go values.

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrParseDA = errors.New(
	"error parsing dicom DA (date) value -- expected format is 'YYYYMMDD'. " +
		"for more details on proper DA value formatting, see here: " +
		"https://dicom.nema.org/medical/dicom/current/output/html/part05.html#table_6.2-1",
)

ErrParseDA is a sentinel error returned from ParseDate.

View Source
var ErrParseDT = errors.New(
	"error parsing dicom DT (datetime) value -- expected format is" +
		" 'YYYYMMDDHHMMSS.FFFFFF&ZZXX'. " +
		"for more details on proper DT value formatting, see here: " +
		"https://dicom.nema.org/medical/dicom/current/output/html/part05.html#table_6.2-1",
)

ErrParseDA is a sentinel error returned from ParseDatetime.

View Source
var ErrParseTM = errors.New(
	"error parsing dicom TM (time) value, but expected format is 'HHMMSS.FFFFFF'. " +
		"for more details on proper TM value formatting, see here: " +
		"https://dicom.nema.org/medical/dicom/current/output/html/part05.html#table_6.2-1",
)

ErrParseTM is a sentinel error returned from ParseTime.

Functions

This section is empty.

Types

type Date

type Date struct {
	// Time is the underlying time.Time value.
	Time time.Time

	// Precision with which the raw DA value was stored. For instance, a Date value
	// with a precision of PrecisionYear ONLY stored the year.
	Precision PrecisionLevel

	// IsNEMA will be true if this is a legacy NEMA-300 formatted value (1999.01.03).
	IsNEMA bool
}

Date holds data for a parsed DICOM date (DA value).

Example (Create)
// We'll use the reference date as our date
date, err := time.Parse(
	"Mon Jan 2, 2006",
	"Mon Jan 2, 2006",
)
if err != nil {
	panic(err)
}

// Create a nw DA object like so:
da := Date{
	Time:      date,
	Precision: PrecisionFull,
	IsNEMA:    false,
}

// Get the DICOM string value
fmt.Println("DCM   :", da.DCM())

// Our String() method will yield a more readable non-DICOM-compliant value.
fmt.Println("STRING:", da.String())
Output:

DCM   : 20060102
STRING: 2006-01-02
Example (CreateNEMA300)
// We'll use the reference date as our date
date, err := time.Parse(
	"Mon Jan 2, 2006",
	"Mon Jan 2, 2006",
)
if err != nil {
	panic(err)
}

// Create a nw DA object like so:
da := Date{
	Time:      date,
	Precision: PrecisionFull,
	IsNEMA:    true,
}

// Get the DICOM string value, this will have period separators ala NEMA-300.
fmt.Println("DCM   :", da.DCM())

// Our String() method will yield a more readable non-DICOM-compliant value.
fmt.Println("STRING:", da.String())
Output:

DCM   : 2006.01.02
STRING: 2006-01-02
Example (PrecisionYear)
// We'll use the reference date as our date
date, err := time.Parse("2006-01", "2006-01")
if err != nil {
	panic(err)
}

// Create a nw DA object that only represent the year like so:
da := Date{
	Time:      date,
	Precision: PrecisionMonth,
	IsNEMA:    false,
}

// Get the DICOM string value
fmt.Println("DCM   :", da.DCM())

// Our String() method will yield a more readable non-DICOM-compliant value.
fmt.Println("STRING:", da.String())
Output:

DCM   : 200601
STRING: 2006-01

func ParseDate

func ParseDate(daString string) (Date, error)

ParseDate converts DICOM DA (date) value to time.Time as UTC with PrecisionLevel.

Example

Parse a date string.

// This is a DA value like we would expect
daString := "20201210"

// We are parsing the date string without allowing nema
da, err := ParseDate(daString)
if err != nil {
	panic(err)
}

fmt.Println("TIME VALUE:", da.Time)
fmt.Println("PRECISION :", da.Precision)
Output:

TIME VALUE: 2020-12-10 00:00:00 +0000 +0000
PRECISION : FULL
Example (LessPrecision)

Parse a date string missing dat values.

// This is a DA value like we would expect, but it is missing the day value.
daString := "202012"

// We are parsing the date string without allowing NEMA-300 formatted dates.
da, err := ParseDate(daString)
if err != nil {
	panic(err)
}

// The resulting da value contains a native time.Time value.
fmt.Println("TIME MONTH:", da.Time.Month())
// It also reports the precision, of the value. This value is Precision.Month,
// so we know that even though da.Time.Day() will equal 1, we should disregard it.

fmt.Println("PRECISION :", da.Precision)

// This date is not a NEMA-300 date.
fmt.Println("IS NEMA   :", da.IsNEMA)
Output:

TIME MONTH: December
PRECISION : MONTH
IS NEMA   : false
Example (Nema)

Parse a NEMA date string.

// This is a DA value using the legacy NEMA-format.
daString := "2020.12.10"

da, err := ParseDate(daString)
if err != nil {
	panic(err)
}

fmt.Println("TIME VALUE:", da.Time)
fmt.Println("PRECISION :", da.Precision)
// This is a NEMA-300 date.
fmt.Println("IS NEMA   :", da.IsNEMA)
Output:

TIME VALUE: 2020-12-10 00:00:00 +0000 +0000
PRECISION : FULL
IS NEMA   : true

func (Date) DCM

func (da Date) DCM() string

DCM converts time.Time value to dicom DA string. Values are truncated to the Date.Precision value.

NOTE: Time zones are ignored in this operation, as DA does not support encoding them. Make sure values are converted to UTC before passing if that is the desired output.

func (Date) String

func (da Date) String() string

String implements fmt.Stringer.

type Datetime

type Datetime struct {
	// Time is the underlying time.Time value.
	Time time.Time
	// Precision with which this value was stored. For instance, a DT value with a
	// precision of PrecisionYear ONLY stored the year.
	Precision PrecisionLevel
	// NoOffset: if false, offset information was not specifically included in the
	// original DT string, and will not be rendered with DCM()
	//
	// We use the negated version here for safer defaults - by default, without setting
	// this field explicitly, the timezone will be included.
	NoOffset bool
}

Datetime holds data for a parsed DICOM datetime (DT) value.

Example (Create)
// We'll use the reference date as our date
timeVal, err := time.Parse(
	"2006-01-02T15:04:05.000000-07:00",
	"2006-01-02T15:04:05.123456+01:00",
)
if err != nil {
	panic(err)
}

// Create a nw TM object like so:
dt := Datetime{
	Time:      timeVal,
	Precision: PrecisionFull,
	NoOffset:  false,
}

// Get the DICOM string value
fmt.Println("DCM   :", dt.DCM())

// Our String() method will yield a more readable non-DICOM-compliant value.
fmt.Println("STRING:", dt.String())
Output:

DCM   : 20060102150405.123456+0100
STRING: 2006-01-02 15:04:05.123456 +01:00
Example (CreateNoOffset)
// We'll use the reference date as our date
timeVal, err := time.Parse(
	"2006-01-02T15:04:05.000000",
	"2006-01-02T15:04:05.123456",
)
if err != nil {
	panic(err)
}

// Create a nw TM object like so:
dt := Datetime{
	Time:      timeVal,
	Precision: PrecisionFull,
	NoOffset:  true,
}

// Get the DICOM string value
fmt.Println("DT:", dt.DCM())
Output:

DT: 20060102150405.123456
Example (PrecisionMinute)
// We'll use the reference date as our date
timeVal, err := time.Parse(
	"2006-01-02T15:04",
	"2006-01-02T15:04",
)
if err != nil {
	panic(err)
}

// Create a nw TM object like so:
dt := Datetime{
	Time:      timeVal,
	Precision: PrecisionMinutes,
	NoOffset:  true,
}

// Get the DICOM string value
fmt.Println("DT:", dt.DCM())
Output:

DT: 200601021504
Example (PrecisionMinuteWithOffset)
// We'll use the reference date as our date
timeVal, err := time.Parse(
	"2006-01-02T15:04-07:00",
	"2006-01-02T15:04+01:00",
)
if err != nil {
	panic(err)
}

// Create a nw TM object like so:
dt := Datetime{
	Time:      timeVal,
	Precision: PrecisionMinutes,
	NoOffset:  false,
}

// Get the DICOM string value
fmt.Println("DT:", dt.DCM())
Output:

DT: 200601021504+0100

func ParseDatetime

func ParseDatetime(dtString string) (Datetime, error)

ParseDatetime converts DICOM DT (datetime) value to time.Time, PrecisionLevel, and offset presence as UTC.

Example

Parse a datetime string.

// This is a DT value like we would expect
daString := "20201210123001.000431+0100"

// We are parsing the date string without allowing nema
dt, err := ParseDatetime(daString)
if err != nil {
	panic(err)
}

fmt.Println("TIME VALUE:", dt.Time)
fmt.Println("PRECISION :", dt.Precision)
fmt.Println("NO OFFSET :", dt.NoOffset)
Output:

TIME VALUE: 2020-12-10 12:30:01.000431 +0100 +0100
PRECISION : FULL
NO OFFSET : false
Example (NoTimezone)

Parse a datetime string with no timezone.

// This is a DT value like we would expect
daString := "20201210123001.000431"

// We are parsing the date string without allowing nema
dt, err := ParseDatetime(daString)
if err != nil {
	panic(err)
}

fmt.Println("TIME VALUE:", dt.Time)
fmt.Println("PRECISION :", dt.Precision)
fmt.Println("NO OFFSET :", dt.NoOffset)
Output:

TIME VALUE: 2020-12-10 12:30:01.000431 +0000 +0000
PRECISION : FULL
NO OFFSET : true
Example (PrecisionHour)

Parse a datetime string with no timezone.

// This is a DT value like we would expect
daString := "2020121012"

// We are parsing the date string without allowing nema
dt, err := ParseDatetime(daString)
if err != nil {
	panic(err)
}

fmt.Println("TIME VALUE:", dt.Time)
fmt.Println("PRECISION :", dt.Precision)
fmt.Println("NO OFFSET :", dt.NoOffset)
Output:

TIME VALUE: 2020-12-10 12:00:00 +0000 +0000
PRECISION : HOURS
NO OFFSET : true

func (Datetime) DCM

func (dt Datetime) DCM() string

DCM converts time.Time value to dicom DT string. Values are truncated to the DT.Precision value.

If NoOffset is true, no offset will be encoded.

func (Datetime) String

func (dt Datetime) String() string

String implements fmt.Stringer.

type PrecisionLevel

type PrecisionLevel int

PrecisionLevel tells encoding methods how many segments of the value to render to the DICOM format string, as the spec allows eliding segments to communicate the precision.

For instance: when rendering a DA (date) value, using a truncation of PrecisionYear would render the entire date as 'YYYY'.

Using PrecisionMonth would render 'YYYYMM'.

Using PrecisionDay or PrecisionFull would render a full 'YYYYMMDD'.

const (
	// PrecisionFull indicates that a given dcm time value is precise to the full extent
	// it is able to be.
	PrecisionFull PrecisionLevel = iota
	// PrecisionMS5 indicated that a given dcm time value is only precise to 4
	// millisecond place (1/100000 of a second).
	PrecisionMS5
	// PrecisionMS4 indicated that a given dcm time value is only precise to 4
	// millisecond place (1/10000 of a second).
	PrecisionMS4
	// PrecisionMS3 indicated that a given dcm time value is only precise to 3
	// millisecond place (1/1000 of a second).
	PrecisionMS3
	// PrecisionMS2 indicated that a given dcm time value is only precise to 2
	// millisecond place (1/100 of a second).
	PrecisionMS2
	// PrecisionMS1 indicated that a given dcm time value is only precise to 1
	// millisecond place (1/10 of a second).
	PrecisionMS1
	// PrecisionSeconds indicated that a given dcm time value is only precise to the
	// second.
	PrecisionSeconds
	// PrecisionMinutes indicated that a given dcm time value is only precise to the
	// minute.
	PrecisionMinutes
	// PrecisionHours indicated that a given dcm time value is only precise to the hour.
	PrecisionHours
	// PrecisionDay indicated that a given dcm time value is only precise to the day.
	PrecisionDay
	// PrecisionMonth indicated that a given dcm time value is only precise to the
	// month.
	PrecisionMonth
	// PrecisionYear indicated that a given dcm time value is only precise to the year.
	PrecisionYear
)

func (PrecisionLevel) String

func (level PrecisionLevel) String() string

String returns the name of the PrecisionLevel for debugging.

type Time

type Time struct {
	// Time is the underlying time.Time value.
	Time time.Time
	// Precision with which the raw TM value was stored. For instance, a Date value
	// with a precision of PrecisionHours ONLY stored the Hour.
	Precision PrecisionLevel
}

Time holds data for a parsed DICOM time (TM) value.

Example (Create)
// We'll use the reference date as our date
timeVal, err := time.Parse(
	"15:04:05.000",
	"15:04:05.431",
)
if err != nil {
	panic(err)
}

// Create a nw TM object like so:
tm := Time{
	Time:      timeVal,
	Precision: PrecisionFull,
}

// Get the DICOM string value
fmt.Println("DCM   :", tm.DCM())

// Our String() method will yield a more readable non-DICOM-compliant value.
fmt.Println("STRING:", tm.String())
Output:

DCM   : 150405.431000
STRING: 15:04:05.431000
Example (Precision3MS)
// We'll use the reference date as our date
timeVal, err := time.Parse(
	"15:04:05.000",
	"15:04:05.431",
)
if err != nil {
	panic(err)
}

// Create a nw TM object like so:
tm := Time{
	Time:      timeVal,
	Precision: PrecisionMS3,
}

// Get the DICOM string value
fmt.Println("DCM   :", tm.DCM())

// Our String() method will yield a more readable non-DICOM-compliant value.
fmt.Println("STRING:", tm.String())
Output:

DCM   : 150405.431
STRING: 15:04:05.431
Example (PrecisionMinutes)
// We'll use the reference date as our date
timeVal, err := time.Parse(
	"15:04",
	"15:04",
)
if err != nil {
	panic(err)
}

// Create a nw TM object like so:
tm := Time{
	Time:      timeVal,
	Precision: PrecisionMinutes,
}

// Get the DICOM string value
fmt.Println("DCM   :", tm.DCM())

// Our String() method will yield a more readable non-DICOM-compliant value.
fmt.Println("STRING:", tm.String())
Output:

DCM   : 1504
STRING: 15:04

func ParseTime

func ParseTime(tmString string) (Time, error)

ParseTime converts DICOM TM (time) value to dcmtime.Time.

Example
// This is a TM value like we would expect for 12:30:01 and 400 microseconds
tmString := "123001.000431"

tm, err := ParseTime(tmString)
if err != nil {
	panic(err)
}

fmt.Println("TIME VALUE:", tm.Time)
fmt.Println("PRECISION :", tm.Precision)
Output:

TIME VALUE: 0001-01-01 12:30:01.000431 +0000 +0000
PRECISION : FULL
Example (PrecisionHour)
// This is a TM value like we would expect for 12:30:01 and 400 microseconds
tmString := "12"

tm, err := ParseTime(tmString)
if err != nil {
	panic(err)
}

fmt.Println("TIME VALUE:", tm.Time)
fmt.Println("PRECISION :", tm.Precision)
Output:

TIME VALUE: 0001-01-01 12:00:00 +0000 +0000
PRECISION : HOURS
Example (PrecisionMS)
// This is a TM value like we would expect for 12:30:01 and 400 microseconds
tmString := "123001.431"

tm, err := ParseTime(tmString)
if err != nil {
	panic(err)
}

fmt.Println("TIME VALUE:", tm.Time)
fmt.Println("PRECISION :", tm.Precision)
Output:

TIME VALUE: 0001-01-01 12:30:01.431 +0000 +0000
PRECISION : MS3

func (Time) DCM

func (tm Time) DCM() string

DCM converts internal time.Time value to dicom TM string, truncating the output to the DA value's Precision.

NOTE: Time zones are ignored in this operation, as TM does not support encoding them. Make sure values are converted to UTC before passing if that is the desired output.

func (Time) String

func (tm Time) String() string

String implements fmt.Stringer.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL