You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							107 lines
						
					
					
						
							2.5 KiB
						
					
					
				
			
		
		
	
	
							107 lines
						
					
					
						
							2.5 KiB
						
					
					
				| type DateTime = {
 | |
|   /** The date formatted as a string
 | |
|    * @example
 | |
|    * 'January 1, 2022'
 | |
|    * 'December 31, 2022'
 | |
|    */
 | |
|   asString: string;
 | |
|   /** The date formatted as an ISO string
 | |
|    * @example
 | |
|    * '2022-01-01T00:00:00.000Z'
 | |
|    */
 | |
|   asISOString: string;
 | |
|   /** The date formatted as a relative time string
 | |
|    * @example
 | |
|    * '2 days ago'
 | |
|    * '3 weeks ago'
 | |
|    */
 | |
|   asRelativeTimeString: string;
 | |
|   /** A boolean indicating if the date is fresh, i.e. less than 4 days old */
 | |
|   isFresh: boolean;
 | |
| };
 | |
| 
 | |
| const dateFormatter = new Intl.DateTimeFormat('en-US', {
 | |
|   month: 'long',
 | |
|   day: 'numeric',
 | |
|   year: 'numeric',
 | |
| });
 | |
| 
 | |
| const relativeTimeFormatter = new Intl.RelativeTimeFormat('en-US', {
 | |
|   numeric: 'auto',
 | |
| });
 | |
| 
 | |
| /**
 | |
|  * Formats a date string into a {@link DateTime} object.
 | |
|  * @example
 | |
|  * const dateTime = formatDateTime('2022-01-01');
 | |
|  * // dateTime = {
 | |
|  * //   asString: 'January 1, 2022',
 | |
|  * //   asISOString: '2022-01-01T00:00:00.000Z',
 | |
|  * //   asRelativeTimeString: '2 days ago',
 | |
|  * //   isFresh: true
 | |
|  * // }
 | |
|  */
 | |
| export function formatDateTime(dateString: string): DateTime {
 | |
|   const date = new Date(dateString);
 | |
| 
 | |
|   if (isNaN(date.getTime())) {
 | |
|     return {
 | |
|       asString: 'Invalid Date',
 | |
|       asISOString: 'Invalid Date',
 | |
|       asRelativeTimeString: 'Invalid Date',
 | |
|       isFresh: false,
 | |
|     };
 | |
|   }
 | |
| 
 | |
|   const { relativeTime, isFresh } = getRelativeTime(date);
 | |
| 
 | |
|   return {
 | |
|     asString: dateFormatter.format(date),
 | |
|     asISOString: date.toISOString(),
 | |
|     asRelativeTimeString: relativeTime,
 | |
|     isFresh,
 | |
|   };
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Formats a date into a relative time.
 | |
|  * @returns The relative time string and a boolean indicating if the date is fresh,
 | |
|  * i.e. less than 4 days old
 | |
|  * @example
 | |
|  * const { relativeTime, isFresh } = getRelativeTime(someDate);
 | |
|  * // relativeTime = '3 weeks ago'
 | |
|  * // isFresh = false
 | |
|  */
 | |
| function getRelativeTime(date: Date) {
 | |
|   const timeDiff = date.getTime() - new Date().getTime();
 | |
| 
 | |
|   const days = Math.ceil(timeDiff / (1000 * 60 * 60 * 24));
 | |
|   if (days > -14) {
 | |
|     return {
 | |
|       relativeTime: relativeTimeFormatter.format(days, 'day'),
 | |
|       isFresh: days > -4,
 | |
|     };
 | |
|   }
 | |
| 
 | |
|   const weeks = Math.floor(days / 7);
 | |
|   if (weeks > -8) {
 | |
|     return {
 | |
|       relativeTime: relativeTimeFormatter.format(weeks, 'week'),
 | |
|       isFresh: false,
 | |
|     };
 | |
|   }
 | |
| 
 | |
|   const months = Math.floor(days / 30);
 | |
|   if (months > -12) {
 | |
|     return {
 | |
|       relativeTime: relativeTimeFormatter.format(months, 'month'),
 | |
|       isFresh: false,
 | |
|     };
 | |
|   }
 | |
| 
 | |
|   const years = Math.floor(days / 365);
 | |
|   return {
 | |
|     relativeTime: relativeTimeFormatter.format(years, 'year'),
 | |
|     isFresh: false,
 | |
|   };
 | |
| }
 | |
| 
 |