@nerdo/utils v2.1.0
@nerdo/utils
nerdo's JavaScript utilities.
Install it:
npm install @nerdo/utils --saveisDateObject(object)
import { isDateObject } from '@nerdo/utils'
Tests whether an object is a Date object.
object{object}: the object in question.
isDateObject(...) returns true if the object is a Date object, false otherwise.
map(object, mapper)
import { map } from '@nerdo/utils'
A recursive mapping function for objects.
object{object}: the object to map.mapper{function}: a function that handles the mapping.
map(...) returns the object
map traverses key-value pairs in an object recursively, calling the mapper on it and replacing each value with what the mapper returns.
mapper has the signature mapper(value, {object, path}).
value{mixed}: the current value being mapped.object{object}: the root object the mapping is being performed on.path: {array}: the list of keys identifying to the current value being mapped.
Here is simple example, filtering out all values that are numeric from the object:
const obj = {
name: 'John Doe',
age: 42,
dateOfBirth: new Date(1973, 1, 7),
misc: {
height: 136,
weight: 159
}
}
const mapper = v => typeof v === 'number' ? undefined : v
map(obj, mapper)
console.log(obj) // {name: 'John Doe', dateOfBirth: 'Wed Feb 07 1973...', misc: {}}Note, that the mapper will not traverse a value that is an object that has been removed by the mapper. Here is an example:
const obj = {
foo: {
removeMe: false,
bar: {
removeMe: true,
ignored: {
removeMe: true
}
}
}
}
const mapper = function (v, {path}) {
console.log(path.join('.'))
return v.removeMe ? undefined : v
}
mapper(obj, mapper) // foo, foo.bar
console.log(obj) // {foo: {removeMe: false }}Although both foo.bar and foo.bar.ignored have been removed by the mapper, the console logs confirm that the mapper never actually iterated on foo.bar.ignored. It was removed because it was a property of foo.bar, which was removed.
clone(object)
import { clone } from '@nerdo/utils'
Returns a deep clone of the specified object
object{object}: the object to clone.
clone(...) returns the deep cloned object
const obj = {
a: [
9,
{
foo: 'bar'
},
7
]
}
const cloned = clone(obj)
console.log(cloned) // a deep clone of objget(object, path, defaultValue = undefined)
import { get } from '@nerdo/utils'
Returns the value in an object at the location specified by path.
object{object}: the object to query.path{string|array}: the dotted-key string path or array path of the property to get.defaultValue{mixed} undefined: the default value to return if the property path cannot be fully resolved.
get(...) returns the value, or defaultValue if the property path could not be fully resolved.
The path may be specified using either dotted-key or array path syntax. If the path cannot be fully resolved, the defaultValue is returned. For example:
const object = {a: [{b: {c: 3}}]}
get(object, 'a[0].b.c') // 3
get(object, ['a', 0, 'b', 'c']) // 3
get(object, 'a.b.c', 555) // 5representMonth({ date, startingDayOfWeek })
import { representMonth } from '@nerdo/utils'
Generates an object representation of a calendar date.
date{representMonth.DateAdapter} new representMonth.DateAdapter(): the date to be represented.startingDayOfWeek{representMonth.DayOfWeek} representMonth.DayOfWeek.Sunday: the starting day of the week.
Properties:
DateAdapter{Date}: a constructor that is compatible with the JavaScriptDateobject.
representMonth(...) returns an object with the following structure:
date{representMonth.DateAdapter}: therepresentMonth.DateAdapterinstance of the date being represented.numberOfDays{number}: the number of days in the monthweeks{(number | null)}: the list of days in each week (i.e. 1 through 31 depending on the month). Each week array will always represent each of the 7 days and the first index of the week corresponds to thestartingDayOfWeekargument. If a value isnull, that particular day does not exist in the month. This is visually equivalent to when there are blank spaces in a calendar in the first and last weeks of a month that overlap with the previous month.prevMonthNumberOfDays{number}: the number of days in the previous monthprevMonthLastWeek{(number | null)[]}: the last week of the previous month that overlaps with the first week of the current month.nextMonthNumberOfDays{number}: the number of days in the next monthnextMonthFirstWeek{(number | null)[]}: the first week of the next month that overlaps with the last week of the current month.
A typical usage of this is to render calendars. For example:
const monthNames = [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December'
]
const year = 2020
const cellSize = 4
const calWidth = 7 * cellSize + 8
monthNames.forEach((monthName, index) => {
const label = `${monthName} ${year}`
console.log(`${' '.repeat((calWidth - label.length) / 2)}${label}`) // centers the label over the calendar
const representation = representMonth({date: new Date(year, index)}) //?
const renderData: (string | number | null)[][] = [['S', 'M', 'T', 'W', 'T', 'F', 'S']]
renderData
.concat(representation.weeks)
.map((week) => week
.map((day) => `${day || ''}`) // coerce each day to a string
.map((stringDay) => stringDay.padStart(cellSize, ' '))
.join(' ')
)
.forEach((weekString) => console.log(weekString))
})The preceeding code results in console logging of each month of the 2020 calendar year.
Here's a slightly more advanced example which uses the data to console log calendar months with previous and next months days showing up in square brackets (e.g. 30)
const monthNames = [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December'
]
const year = 2020
const cellSize = 6
const calWidth = 7 * cellSize + 8
monthNames.forEach((monthName, index) => {
const label = `${monthName} ${year}`
console.log(`${' '.repeat((calWidth - label.length) / 2)}${label}`) // centers the label over the calendar
const representation = representMonth({date: new Date(year, index)}) //?
const renderData: (string | number | null)[][] = [['S', 'M', 'T', 'W', 'T', 'F', 'S']]
renderData
.concat(representation.weeks)
.map((week, weekIndex) => {
// checking weekIndex as if it were 1-based because we added the header for the week day labels
const maybeFirstWeek = weekIndex === 1 ? representation.prevMonthLastWeek : void 0
const maybeLastWeek = weekIndex === representation.weeks.length ? representation.nextMonthFirstWeek : void 0
const edgeWeek = maybeFirstWeek || maybeLastWeek
return week
.map((day, index) => { // coerce each day to a string
if (edgeWeek && edgeWeek[index]) return `[${edgeWeek[index] || ''}]`
return `${day || ''}`
})
.map((stringDay) => stringDay.padStart(cellSize, ' '))
.join(' ')
})
.forEach((weekString) => console.log(weekString))
})isLeapYear(year: number): boolean
import { isLeapYear } from '@nerdo/utils'
Whether or not the year is a leap year.
year{number} the year
numDaysInMonth(month: number, year: number): number
import { numDaysInMonth } from '@nerdo/utils'
Gets the number of days in a calendar month.
month{number} the month; 0 = January, 11 = Decemberyear{number} the year
DayOfWeek
import { DayOfWeek } from '@nerdo/utils'
An object representing the days of the week for use in representMonth().
Properties:
SundayMondayTuesdayWednesdayThursdaySaturday
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
4 years ago
4 years ago
5 years ago
6 years ago
6 years ago
6 years ago
6 years ago