Path: blob/main/extensions/copilot/src/util/vs/base/common/date.ts
13405 views
//!!! DO NOT modify, this file was COPIED from 'microsoft/vscode'12/*---------------------------------------------------------------------------------------------3* Copyright (c) Microsoft Corporation. All rights reserved.4* Licensed under the MIT License. See License.txt in the project root for license information.5*--------------------------------------------------------------------------------------------*/67import { localize } from '../../nls';8import { Lazy } from './lazy';9import { LANGUAGE_DEFAULT } from './platform';1011const minute = 60;12const hour = minute * 60;13const day = hour * 24;14const week = day * 7;15const month = day * 30;16const year = day * 365;1718/**19* Create a localized difference of the time between now and the specified date.20* @param date The date to generate the difference from.21* @param appendAgoLabel Whether to append the " ago" to the end.22* @param useFullTimeWords Whether to use full words (eg. seconds) instead of23* shortened (eg. secs).24* @param disallowNow Whether to disallow the string "now" when the difference25* is less than 30 seconds.26*/27export function fromNow(date: number | Date, appendAgoLabel?: boolean, useFullTimeWords?: boolean, disallowNow?: boolean): string {28if (typeof date === 'undefined') {29return localize('date.fromNow.unknown', 'unknown');30}3132if (typeof date !== 'number') {33date = date.getTime();34}3536const seconds = Math.round((new Date().getTime() - date) / 1000);37if (seconds < -30) {38return localize('date.fromNow.in', 'in {0}', fromNow(new Date().getTime() + seconds * 1000, false));39}4041if (!disallowNow && seconds < 30) {42return localize('date.fromNow.now', 'now');43}4445let value: number;46if (seconds < minute) {47value = seconds;4849if (appendAgoLabel) {50if (value === 1) {51return useFullTimeWords52? localize('date.fromNow.seconds.singular.ago.fullWord', '{0} second ago', value)53: localize('date.fromNow.seconds.singular.ago', '{0} sec ago', value);54} else {55return useFullTimeWords56? localize('date.fromNow.seconds.plural.ago.fullWord', '{0} seconds ago', value)57: localize('date.fromNow.seconds.plural.ago', '{0} secs ago', value);58}59} else {60if (value === 1) {61return useFullTimeWords62? localize('date.fromNow.seconds.singular.fullWord', '{0} second', value)63: localize('date.fromNow.seconds.singular', '{0} sec', value);64} else {65return useFullTimeWords66? localize('date.fromNow.seconds.plural.fullWord', '{0} seconds', value)67: localize('date.fromNow.seconds.plural', '{0} secs', value);68}69}70}7172if (seconds < hour) {73value = Math.round(seconds / minute);74if (appendAgoLabel) {75if (value === 1) {76return useFullTimeWords77? localize('date.fromNow.minutes.singular.ago.fullWord', '{0} minute ago', value)78: localize('date.fromNow.minutes.singular.ago', '{0} min ago', value);79} else {80return useFullTimeWords81? localize('date.fromNow.minutes.plural.ago.fullWord', '{0} minutes ago', value)82: localize('date.fromNow.minutes.plural.ago', '{0} mins ago', value);83}84} else {85if (value === 1) {86return useFullTimeWords87? localize('date.fromNow.minutes.singular.fullWord', '{0} minute', value)88: localize('date.fromNow.minutes.singular', '{0} min', value);89} else {90return useFullTimeWords91? localize('date.fromNow.minutes.plural.fullWord', '{0} minutes', value)92: localize('date.fromNow.minutes.plural', '{0} mins', value);93}94}95}9697if (seconds < day) {98value = Math.round(seconds / hour);99if (appendAgoLabel) {100if (value === 1) {101return useFullTimeWords102? localize('date.fromNow.hours.singular.ago.fullWord', '{0} hour ago', value)103: localize('date.fromNow.hours.singular.ago', '{0} hr ago', value);104} else {105return useFullTimeWords106? localize('date.fromNow.hours.plural.ago.fullWord', '{0} hours ago', value)107: localize('date.fromNow.hours.plural.ago', '{0} hrs ago', value);108}109} else {110if (value === 1) {111return useFullTimeWords112? localize('date.fromNow.hours.singular.fullWord', '{0} hour', value)113: localize('date.fromNow.hours.singular', '{0} hr', value);114} else {115return useFullTimeWords116? localize('date.fromNow.hours.plural.fullWord', '{0} hours', value)117: localize('date.fromNow.hours.plural', '{0} hrs', value);118}119}120}121122if (seconds < week) {123value = Math.round(seconds / day);124if (appendAgoLabel) {125return value === 1126? localize('date.fromNow.days.singular.ago', '{0} day ago', value)127: localize('date.fromNow.days.plural.ago', '{0} days ago', value);128} else {129return value === 1130? localize('date.fromNow.days.singular', '{0} day', value)131: localize('date.fromNow.days.plural', '{0} days', value);132}133}134135if (seconds < month) {136value = Math.round(seconds / week);137if (appendAgoLabel) {138if (value === 1) {139return useFullTimeWords140? localize('date.fromNow.weeks.singular.ago.fullWord', '{0} week ago', value)141: localize('date.fromNow.weeks.singular.ago', '{0} wk ago', value);142} else {143return useFullTimeWords144? localize('date.fromNow.weeks.plural.ago.fullWord', '{0} weeks ago', value)145: localize('date.fromNow.weeks.plural.ago', '{0} wks ago', value);146}147} else {148if (value === 1) {149return useFullTimeWords150? localize('date.fromNow.weeks.singular.fullWord', '{0} week', value)151: localize('date.fromNow.weeks.singular', '{0} wk', value);152} else {153return useFullTimeWords154? localize('date.fromNow.weeks.plural.fullWord', '{0} weeks', value)155: localize('date.fromNow.weeks.plural', '{0} wks', value);156}157}158}159160if (seconds < year) {161value = Math.round(seconds / month);162if (appendAgoLabel) {163if (value === 1) {164return useFullTimeWords165? localize('date.fromNow.months.singular.ago.fullWord', '{0} month ago', value)166: localize('date.fromNow.months.singular.ago', '{0} mo ago', value);167} else {168return useFullTimeWords169? localize('date.fromNow.months.plural.ago.fullWord', '{0} months ago', value)170: localize('date.fromNow.months.plural.ago', '{0} mos ago', value);171}172} else {173if (value === 1) {174return useFullTimeWords175? localize('date.fromNow.months.singular.fullWord', '{0} month', value)176: localize('date.fromNow.months.singular', '{0} mo', value);177} else {178return useFullTimeWords179? localize('date.fromNow.months.plural.fullWord', '{0} months', value)180: localize('date.fromNow.months.plural', '{0} mos', value);181}182}183}184185value = Math.round(seconds / year);186if (appendAgoLabel) {187if (value === 1) {188return useFullTimeWords189? localize('date.fromNow.years.singular.ago.fullWord', '{0} year ago', value)190: localize('date.fromNow.years.singular.ago', '{0} yr ago', value);191} else {192return useFullTimeWords193? localize('date.fromNow.years.plural.ago.fullWord', '{0} years ago', value)194: localize('date.fromNow.years.plural.ago', '{0} yrs ago', value);195}196} else {197if (value === 1) {198return useFullTimeWords199? localize('date.fromNow.years.singular.fullWord', '{0} year', value)200: localize('date.fromNow.years.singular', '{0} yr', value);201} else {202return useFullTimeWords203? localize('date.fromNow.years.plural.fullWord', '{0} years', value)204: localize('date.fromNow.years.plural', '{0} yrs', value);205}206}207}208209export function fromNowByDay(date: number | Date, appendAgoLabel?: boolean, useFullTimeWords?: boolean): string {210if (typeof date !== 'number') {211date = date.getTime();212}213214const todayMidnightTime = new Date();215todayMidnightTime.setHours(0, 0, 0, 0);216const yesterdayMidnightTime = new Date(todayMidnightTime.getTime());217yesterdayMidnightTime.setDate(yesterdayMidnightTime.getDate() - 1);218219if (date > todayMidnightTime.getTime()) {220return localize('today', 'Today');221}222223if (date > yesterdayMidnightTime.getTime()) {224return localize('yesterday', 'Yesterday');225}226227return fromNow(date, appendAgoLabel, useFullTimeWords);228}229230/**231* Gets a readable duration with intelligent/lossy precision. For example "40ms" or "3.040s")232* @param ms The duration to get in milliseconds.233* @param useFullTimeWords Whether to use full words (eg. seconds) instead of234* shortened (eg. secs).235*/236export function getDurationString(ms: number, useFullTimeWords?: boolean) {237const seconds = Math.abs(ms / 1000);238if (seconds < 1) {239return useFullTimeWords240? localize('duration.ms.full', '{0} milliseconds', ms)241: localize('duration.ms', '{0}ms', ms);242}243if (seconds < minute) {244return useFullTimeWords245? localize('duration.s.full', '{0} seconds', Math.round(ms) / 1000)246: localize('duration.s', '{0}s', Math.round(ms) / 1000);247}248if (seconds < hour) {249return useFullTimeWords250? localize('duration.m.full', '{0} minutes', Math.round(ms / (1000 * minute)))251: localize('duration.m', '{0} mins', Math.round(ms / (1000 * minute)));252}253if (seconds < day) {254return useFullTimeWords255? localize('duration.h.full', '{0} hours', Math.round(ms / (1000 * hour)))256: localize('duration.h', '{0} hrs', Math.round(ms / (1000 * hour)));257}258return localize('duration.d', '{0} days', Math.round(ms / (1000 * day)));259}260261export function toLocalISOString(date: Date): string {262return date.getFullYear() +263'-' + String(date.getMonth() + 1).padStart(2, '0') +264'-' + String(date.getDate()).padStart(2, '0') +265'T' + String(date.getHours()).padStart(2, '0') +266':' + String(date.getMinutes()).padStart(2, '0') +267':' + String(date.getSeconds()).padStart(2, '0') +268'.' + (date.getMilliseconds() / 1000).toFixed(3).slice(2, 5) +269'Z';270}271272export const safeIntl = {273DateTimeFormat(locales?: Intl.LocalesArgument, options?: Intl.DateTimeFormatOptions): Lazy<Intl.DateTimeFormat> {274return new Lazy(() => {275try {276return new Intl.DateTimeFormat(locales, options);277} catch {278return new Intl.DateTimeFormat(undefined, options);279}280});281},282Collator(locales?: Intl.LocalesArgument, options?: Intl.CollatorOptions): Lazy<Intl.Collator> {283return new Lazy(() => {284try {285return new Intl.Collator(locales, options);286} catch {287return new Intl.Collator(undefined, options);288}289});290},291Segmenter(locales?: Intl.LocalesArgument, options?: Intl.SegmenterOptions): Lazy<Intl.Segmenter> {292return new Lazy(() => {293try {294return new Intl.Segmenter(locales, options);295} catch {296return new Intl.Segmenter(undefined, options);297}298});299},300Locale(tag: Intl.Locale | string, options?: Intl.LocaleOptions): Lazy<Intl.Locale> {301return new Lazy(() => {302try {303return new Intl.Locale(tag, options);304} catch {305return new Intl.Locale(LANGUAGE_DEFAULT, options);306}307});308},309NumberFormat(locales?: Intl.LocalesArgument, options?: Intl.NumberFormatOptions): Lazy<Intl.NumberFormat> {310return new Lazy(() => {311try {312return new Intl.NumberFormat(locales, options);313} catch {314return new Intl.NumberFormat(undefined, options);315}316});317}318};319320321