File "formatting.js"
Full path: /home/satkhirabarta/public_html/wp-content/plugins/burst-statistics/settings/src/utils/formatting.js
File
size: 11.71 B (11.71 KB bytes)
MIME-type: text/x-java
Charset: utf-8
Download Open Edit Advanced Editor &nnbsp; Back
import { dateI18n } from '@wordpress/date';
import { format, isSameDay, startOfDay, endOfDay, addDays, addMonths, startOfMonth, endOfMonth, startOfYear, endOfYear, addYears } from 'date-fns';
import {__} from '@wordpress/i18n';
/**
* Returns a formatted string that represents the relative time between two dates
* @param {Date | number} relativeDate - The date to compare or a UTC timestamp
* @param {Date} date - The reference date, defaults to the current date
* @returns {string} The relative time string
*/
const getRelativeTime = ( relativeDate, date = new Date() ) => {
// if relativeDate is a number, we assume it is an UTC timestamp
if ( 'number' === typeof relativeDate ) {
// convert to date object
relativeDate = new Date( relativeDate * 1000 );
}
if ( ! ( relativeDate instanceof Date ) ) {
// invalid date, probably still loading
return '-';
}
let units = {
year: 24 * 60 * 60 * 1000 * 365,
month: 24 * 60 * 60 * 1000 * 365 / 12,
day: 24 * 60 * 60 * 1000,
hour: 60 * 60 * 1000,
minute: 60 * 1000,
second: 1000
};
let rtf = new Intl.RelativeTimeFormat( 'en', { numeric: 'auto' });
let elapsed = relativeDate - date;
// "Math.abs" accounts for both "past" & "future" scenarios
for ( let u in units ) {
if ( Math.abs( elapsed ) > units[u] || 'second' === u ) {
return rtf.format( Math.round( elapsed / units[u]), u );
}
}
};
/**
* Calculates the percentage of a value from the total and returns it as a formatted string or a number
* @param {number} val - The value to calculate the percentage of
* @param {number} total - The total value
* @param {boolean} format - If true, returns the percentage as a formatted string, otherwise as a number
* @returns {string | number} The formatted percentage or the raw percentage
*/
const getPercentage = ( val, total, format = true ) => {
val = Number( val );
total = Number( total );
let percentage = val / total;
if ( isNaN( percentage ) ) {
percentage = 0;
}
return format ? new Intl.NumberFormat(
undefined,
{
style: 'percent',
maximumFractionDigits: 1
}).format( percentage ) : percentage;
};
/**
* Calculates the percentage change between two values and returns an object with the formatted percentage and status
* @param {number} currValue - The current value
* @param {number} prevValue - The previous value
* @returns {Object} An object with a formatted percentage and a status ('positive' or 'negative')
*/
function getChangePercentage( currValue, prevValue ) {
currValue = Number( currValue );
prevValue = Number( prevValue );
let change = {};
let percentage = ( currValue - prevValue ) / prevValue;
if ( isNaN( percentage ) ) {
percentage = 0;
}
change.val = new Intl.NumberFormat(
undefined,
{
style: 'percent',
maximumFractionDigits: 1,
signDisplay: 'exceptZero'
}).format( percentage );
change.status = ( 0 < percentage ) ? 'positive' : 'negative';
if ( percentage === Infinity ) {
change.val = '';
change.status = 'positive';
}
return change;
}
/**
* Calculates the bounce percentage of bounced sessions and total sessions
* @param {number} bounced_sessions - The number of bounced sessions
* @param {number} sessions - The total number of sessions
* @param {boolean} format - If true, returns the bounce percentage as a formatted string, otherwise as a number
* @returns {string | number} The formatted bounce percentage or the raw bounce percentage
*/
function getBouncePercentage( bounced_sessions, sessions, format = true ) {
bounced_sessions = Number( bounced_sessions );
sessions = Number( sessions );
return getPercentage( bounced_sessions, sessions + bounced_sessions, format );
}
/**
* Formats a Unix timestamp as a date string, using the site's locale and wp date format
* @param {number} unixTimestamp - The Unix timestamp to format
* @returns {string} The formatted date string
*/
const formatUnixToDate = ( unixTimestamp ) => {
const formattedDate = dateI18n( burst_settings.date_format, new Date( unixTimestamp * 1000 ) );
return formattedDate;
};
/**
* Check if a date is valid
* @param {string | number} date - The date to check
* @return {boolean}
*/
const isValidDate = ( date ) => {
const MIN_START_DATE = 1640995200 * 1000; // January 1, 2022 in Unix timestamp
return date && ( 'number' === typeof date || Date.parse( date ) >= MIN_START_DATE );
};
/**
* Converts a date to a Unix timestamp in milliseconds
* @param {string | number} date - The date to convert
* @return {number|number|number}
*/
const toUnixTimestampMillis = ( date ) => {
if ( 'number' === typeof date ) {
// If the number is 10 digits long, assume it's in seconds and convert to milliseconds
return 10 === date.toString().length ? date * 1000 : date;
}
// If it's a string, parse it to get milliseconds
return Date.parse( date );
};
/**
* Formats a duration given in milliseconds as a time string in the format 'HH:mm:ss'
* @param {number} timeInMilliSeconds - The duration in milliseconds
* @returns {string} The formatted time string
*/
function formatTime( timeInMilliSeconds = 0 ) {
let timeInSeconds = Number( timeInMilliSeconds );
if ( isNaN( timeInSeconds ) ) {
timeInSeconds = 0;
}
const seconds = Math.floor( timeInSeconds / 1000 );
const hours = Math.floor( seconds / 3600 );
const minutes = Math.floor( ( seconds - ( hours * 3600 ) ) / 60 );
const remainingSeconds = seconds - ( hours * 3600 ) - ( minutes * 60 );
const zeroPad = ( num ) => {
if ( isNaN( num ) ) {
return '00';
}
return String( num ).padStart( 2, '0' );
};
const formatted = [
hours,
minutes,
remainingSeconds
].map( zeroPad );
return formatted.join( ':' );
}
/**
* Formats a number using compact notation with the specified number of decimal places
* @param {number} value - The number to format
* @param {number} decimals - The number of decimal places to use
* @returns {string} The formatted number
*/
function formatNumber( value, decimals = 1 ) {
value = Number( value );
if ( isNaN( value ) ) {
value = 0;
}
return new Intl.NumberFormat( undefined, {
style: 'decimal',
notation: 'compact',
compactDisplay: 'short',
maximumFractionDigits: decimals
}).format( value );
}
/**
* Formats a percentage value with the specified number of decimal places
* @param {number} value - The percentage value (not multiplied by 100)
* @param {number} decimals - The number of decimal places to use
* @returns {string} The formatted percentage
*/
function formatPercentage( value, decimals = 1 ) {
value = Number( value ) / 100;
if ( isNaN( value ) ) {
value = 0;
}
return new Intl.NumberFormat( undefined, {
style: 'percent',
maximumFractionDigits: decimals
}).format( value );
}
/**
* Returns the name of a country based on its country code. If undefined return Unknown
* @param countryCode
* @return {*}
*/
function getCountryName( countryCode ) {
if ( countryCode ) {
return burst_settings.countries[countryCode.toUpperCase()] || __( 'Unknown', 'burst-statistics' );
}
return __( 'Unknown', 'burst-statistics' );
}
function getDateWithOffset( currentDate = new Date() ) {
// get client's timezone offset in minutes
const clientTimezoneOffsetMinutes = currentDate.getTimezoneOffset();
// convert client's timezone offset from minutes to seconds
const clientTimezoneOffsetSeconds = clientTimezoneOffsetMinutes * -60;
// get current unix timestamp
const currentUnix = Math.floor( currentDate.getTime() / 1000 );
// add burst_settings.gmt_offset x hour and client's timezone offset in
// seconds to currentUnix
const currentUnixWithOffsets = currentUnix +
( burst_settings.gmt_offset * 3600 ) - clientTimezoneOffsetSeconds;
const currentDateWithOffset = new Date( currentUnixWithOffsets * 1000 );
return currentDateWithOffset;
}
const currentDateWithOffset = getDateWithOffset();
const availableRanges = {
'today': {
label: __( 'Today', 'burst-statistics' ),
range: () => ({
startDate: startOfDay( currentDateWithOffset ),
endDate: endOfDay( currentDateWithOffset )
})
},
'yesterday': {
label: __( 'Yesterday', 'burst-statistics' ),
range: () => ({
startDate: startOfDay( addDays( currentDateWithOffset, -1 ) ),
endDate: endOfDay( addDays( currentDateWithOffset, -1 ) )
})
},
'last-7-days': {
label: __( 'Last 7 days', 'burst-statistics' ),
range: () => ({
startDate: startOfDay( addDays( currentDateWithOffset, -7 ) ),
endDate: endOfDay( addDays( currentDateWithOffset, -1 ) )
})
},
'last-30-days': {
label: __( 'Last 30 days', 'burst-statistics' ),
range: () => ({
startDate: startOfDay( addDays( currentDateWithOffset, -30 ) ),
endDate: endOfDay( addDays( currentDateWithOffset, -1 ) )
})
},
'last-90-days': {
label: __( 'Last 90 days', 'burst-statistics' ),
range: () => ({
startDate: startOfDay( addDays( currentDateWithOffset, -90 ) ),
endDate: endOfDay( addDays( currentDateWithOffset, -1 ) )
})
},
'last-month': {
label: __( 'Last month', 'burst-statistics' ),
range: () => ({
startDate: startOfMonth( addMonths( currentDateWithOffset, -1 ) ),
endDate: endOfMonth( addMonths( currentDateWithOffset, -1 ) )
})
},
'week-to-date': {
label: __( 'Week to date', 'burst-statistics' ),
range: () => ({
startDate: startOfDay( addDays( currentDateWithOffset, -currentDateWithOffset.getDay() ) ),
endDate: endOfDay( currentDateWithOffset )
})
},
'month-to-date': {
label: __( 'Month to date', 'burst-statistics' ),
range: () => ({
startDate: startOfMonth( currentDateWithOffset ),
endDate: endOfDay( currentDateWithOffset )
})
},
'year-to-date': {
label: __( 'Year to date', 'burst-statistics' ),
range: () => ({
startDate: startOfYear( currentDateWithOffset ),
endDate: endOfDay( currentDateWithOffset )
})
},
'last-year': {
label: __( 'Last year', 'burst-statistics' ),
range: () => ({
startDate: startOfYear( addYears( currentDateWithOffset, -1 ) ),
endDate: endOfYear( addYears( currentDateWithOffset, -1 ) )
})
}
};
const getAvailableRanges = ( selectedRanges ) => {
return Object.values( selectedRanges ).filter( Boolean ).map( ( value ) => {
const range = availableRanges[value];
range.isSelected = isSelected;
return range;
});
};
const getAvailableRangesWithKeys = ( selectedRanges ) => {
let ranges = {};
Object.keys( availableRanges ) // Get the keys from the availableRanges object
.filter( key => selectedRanges.includes( key ) ) // Filter the keys based on selectedRanges
.forEach( key => {
ranges[key] = { // Assign a new object to the key on the ranges object
...availableRanges[key] // Spread the properties from the range object
};
});
return ranges;
};
const getDisplayDates = ( startDate, endDate ) => {
const formatString = 'MMMM d, yyyy';
return {
startDate: startDate ? format( new Date( startDate ), formatString ) : format( defaultStart, formatString ),
endDate: endDate ? format( new Date( endDate ), formatString ) : format( defaultEnd, formatString )
};
};
function isSelected( range ) {
const definedRange = this.range();
return (
isSameDay( range.startDate, definedRange.startDate ) &&
isSameDay( range.endDate, definedRange.endDate )
);
}
export {
getRelativeTime,
getPercentage,
getChangePercentage,
getBouncePercentage,
formatUnixToDate,
isValidDate,
toUnixTimestampMillis,
formatTime,
formatNumber,
formatPercentage,
getCountryName,
getDateWithOffset,
availableRanges,
getAvailableRanges,
getAvailableRangesWithKeys,
getDisplayDates,
isSelected
};