كيف أقوم بتنسيق المدد الزمنية بصيغة 2:30:45؟

عرض المدد الزمنية بتنسيق الساعة الرقمية مع النقطتين

مقدمة

تعرض مشغلات الفيديو وساعات الإيقاف ومؤقتات العد التنازلي المدد الزمنية بتنسيق مألوف. عندما ترى "2:30:45" تفهم فوراً أنها تعني ساعتين و30 دقيقة و45 ثانية. يستخدم تنسيق الساعة الرقمية هذا النقطتين لفصل وحدات الوقت دون تسميات أو مسافات.

يتطلب بناء هذا التنسيق يدوياً إضافة أصفار للأرقام ومعالجة أطوال مختلفة من المدد الزمنية. يعرض فيديو مدته 5 دقائق و30 ثانية "5:30" بينما يعرض فيديو مدته ساعتان "2:00:00". تصبح المنطقية معقدة مع الحالات الاستثنائية.

function formatDuration(seconds) {
  const h = Math.floor(seconds / 3600);
  const m = Math.floor((seconds % 3600) / 60);
  const s = Math.floor(seconds % 60);

  if (h > 0) {
    return `${h}:${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`;
  }
  return `${m}:${String(s).padStart(2, '0')}`;
}

تتعامل واجهة برمجة التطبيقات Intl.DurationFormat مع هذا تلقائياً باستخدام خيار النمط digital. تنتج التنسيق الصحيح لأي طول مدة زمنية.

const duration = { hours: 2, minutes: 30, seconds: 45 };
new Intl.DurationFormat('en', { style: 'digital' }).format(duration);
// "2:30:45"

استخدم النمط الرقمي لعروض المؤقت

ينسق نمط digital المدد الزمنية مثل الساعة الرقمية. اضبط خيار style على "digital" عند إنشاء المنسق.

const formatter = new Intl.DurationFormat('en', { style: 'digital' });

مرر كائن مدة زمنية يحتوي على وحدات الوقت التي تريد عرضها. يضيف المنسق نقطتين بين الوحدات ويضيف أصفاراً للقيم حيثما لزم الأمر.

const duration = { hours: 1, minutes: 5, seconds: 30 };
formatter.format(duration);
// "1:05:30"

لاحظ كيف تعرض الدقائق كـ "05" بدلاً من "5". يضيف المنسق تلقائياً أصفاراً للدقائق لتصبح رقمين عندما تكون الساعات موجودة. يحافظ هذا على المحاذاة في القوائم والجداول.

بالنسبة للمدد الزمنية بدون ساعات، احذف تلك الخاصية من كائن المدة الزمنية.

const shortDuration = { minutes: 5, seconds: 30 };
formatter.format(shortDuration);
// "5:30"

لم تعد الدقائق بحاجة إلى إضافة أصفار عندما تكون الوحدة الأكبر. يبقى التنسيق مضغوطاً مع الحفاظ على الوضوح.

كيف يتعامل التنسيق الرقمي مع أطوال المدة المختلفة

يقوم التنسيق الرقمي بتعديل المخرجات بناءً على الوحدات التي تضمّنها في كائن المدة. وهذا يطابق كيفية تكيّف مشغلات الفيديو لعرضها مع طول الفيديو.

تُظهر المدة القصيرة الدقائق والثواني فقط.

const formatter = new Intl.DurationFormat('en', { style: 'digital' });

const short = { minutes: 3, seconds: 42 };
formatter.format(short);
// "3:42"

تتضمن المدة الأطول الساعات.

const long = { hours: 2, minutes: 15, seconds: 8 };
formatter.format(long);
// "2:15:08"

عندما تظهر الساعات، تُملأ جميع الوحدات الأصغر برقمين. وعندما تكون الساعات غائبة، تُعرض الدقائق بدون حشو لكن الثواني لا تزال تُحشى.

تُنشئ قاعدة الحشو هذه محاذاة متسقة دون إهدار المساحة. تُظهر قائمة من مقاطع الفيديو القصيرة "5:30"، "12:45"، "8:02" مع محاذاة النقطتين. تُظهر قائمة من مقاطع الفيديو الطويلة "1:05:30"، "2:12:45"، "3:08:02" مع تنسيق متسق.

قم بتضمين الوحدات التي تحتاجها واجهتك فقط. يمكن لمؤقت العد التنازلي الذي لا يتجاوز ساعة واحدة أبداً أن يحذف الساعات تماماً.

const countdown = { minutes: 42, seconds: 15 };
formatter.format(countdown);
// "42:15"

التحكم في حشو الأصفار وخيارات العرض

يستخدم التنسيق الرقمي قواعد الحشو الافتراضية، لكن يمكنك تجاوزها من خلال تحديد خيارات لوحدات زمنية فردية.

تحكم في كيفية عرض كل وحدة من خلال تعيين خيارات خاصة بالوحدة. تُظهر قيمة numeric الرقم بدون حشو. تفرض قيمة 2-digit حشو رقمين.

const duration = { hours: 1, minutes: 5, seconds: 3 };

new Intl.DurationFormat('en', {
  style: 'digital',
  hours: 'numeric',
  minutes: '2-digit',
  seconds: '2-digit'
}).format(duration);
// "1:05:03"

هذا هو السلوك الافتراضي. تحتاج فقط إلى تحديد هذه الخيارات عندما تريد تنسيقاً مختلفاً.

فرض عرض الساعات دائماً برقمين.

new Intl.DurationFormat('en', {
  style: 'digital',
  hours: '2-digit',
  minutes: '2-digit',
  seconds: '2-digit'
}).format(duration);
// "01:05:03"

يعمل هذا التنسيق بشكل جيد للعروض المتزامنة حيث يمنع العرض المتسق تحولات التخطيط.

إزالة الحشو من الثواني للحصول على عرض أكثر إحكاماً.

const shortDuration = { minutes: 5, seconds: 3 };

new Intl.DurationFormat('en', {
  style: 'digital',
  seconds: 'numeric'
}).format(shortDuration);
// "5:3"

هذا التنسيق أقل شيوعاً لأن المستخدمين يتوقعون حشو الثواني في العروض الرقمية.

إضافة الثواني الكسرية إلى التنسيق الرقمي

تحتاج بعض التطبيقات إلى عرض الميلي ثانية أو الميكرو ثانية. يدعم التنسيق الرقمي الثواني الكسرية باستخدام خيار fractionalDigits.

حدد عدد المنازل العشرية التي سيتم عرضها بعد الثواني.

const duration = {
  minutes: 5,
  seconds: 30,
  milliseconds: 123
};

new Intl.DurationFormat('en', {
  style: 'digital',
  fractionalDigits: 3
}).format(duration);
// "5:30.123"

يضيف المنسق فاصلة عشرية بعد الثواني ويعرض العدد المحدد من الأرقام الكسرية.

تعرض ساعات الإيقاف عادةً أجزاء المئة من الثانية.

const lap = {
  minutes: 1,
  seconds: 23,
  milliseconds: 450
};

new Intl.DurationFormat('en', {
  style: 'digital',
  fractionalDigits: 2
}).format(lap);
// "1:23.45"

يقوم المنسق بالتقريب إلى الدقة المحددة. تصبح القيمة 450 ميلي ثانية 45 جزءاً من المئة.

للحصول على دقة الميكرو ثانية، قم بتضمين الميكرو ثانية في كائن المدة وحدد أرقاماً كسرية أعلى.

const precise = {
  seconds: 42,
  milliseconds: 123,
  microseconds: 456
};

new Intl.DurationFormat('en', {
  style: 'digital',
  fractionalDigits: 6
}).format(precise);
// "42.123456"

متى يتم استخدام التنسيق الرقمي مقابل الأنماط الأخرى

اختر التنسيق الرقمي عندما تشبه واجهتك مؤقتاً أو ساعة إيقاف أو مشغل وسائط. يتوقع المستخدمون هذا التنسيق في هذه السياقات.

استخدم التنسيق الرقمي لعناصر التحكم في مشغل الفيديو.

function formatVideoTime(seconds) {
  const hours = Math.floor(seconds / 3600);
  const minutes = Math.floor((seconds % 3600) / 60);
  const secs = Math.floor(seconds % 60);

  const duration = hours > 0
    ? { hours, minutes, seconds: secs }
    : { minutes, seconds: secs };

  return new Intl.DurationFormat('en', { style: 'digital' }).format(duration);
}

formatVideoTime(6345); // "1:45:45"
formatVideoTime(125);  // "2:05"

استخدم التنسيق الرقمي لمؤقتات العد التنازلي وساعات الإيقاف.

function formatStopwatch(milliseconds) {
  const minutes = Math.floor(milliseconds / 60000);
  const seconds = Math.floor((milliseconds % 60000) / 1000);
  const ms = milliseconds % 1000;

  return new Intl.DurationFormat('en', {
    style: 'digital',
    fractionalDigits: 2
  }).format({ minutes, seconds, milliseconds: ms });
}

formatStopwatch(125450); // "2:05.45"

استخدم الأنماط الأخرى عند عرض المدد في النص أو عندما تحسن التسميات الوضوح. تعرض مواقع حجز الرحلات الجوية "8 ساعات 15 دقيقة" بدلاً من "8:15:00" لأن السياق ليس مؤقتاً.

// Good for prose and descriptions
new Intl.DurationFormat('en', { style: 'short' }).format(duration);
// "1 hr, 46 min and 40 sec"

// Good for timer displays
new Intl.DurationFormat('en', { style: 'digital' }).format(duration);
// "1:46:40"

إنشاء التنسيق الرقمي يدوياً للمتصفحات القديمة

أصبحت واجهة برمجة التطبيقات Intl.DurationFormat متاحة في مارس 2025. بالنسبة للمتصفحات القديمة، قم بإنشاء التنسيق الرقمي يدوياً.

يتطلب النهج اليدوي حساب وحدات الوقت من إجمالي الثواني وإضافة الأصفار إلى القيم.

function formatDigitalDuration(totalSeconds) {
  const hours = Math.floor(totalSeconds / 3600);
  const minutes = Math.floor((totalSeconds % 3600) / 60);
  const seconds = Math.floor(totalSeconds % 60);

  if (hours > 0) {
    const paddedMinutes = String(minutes).padStart(2, '0');
    const paddedSeconds = String(seconds).padStart(2, '0');
    return `${hours}:${paddedMinutes}:${paddedSeconds}`;
  } else {
    const paddedSeconds = String(seconds).padStart(2, '0');
    return `${minutes}:${paddedSeconds}`;
  }
}

formatDigitalDuration(6345); // "1:45:45"
formatDigitalDuration(125);  // "2:05"

تقسم الدالة إجمالي الثواني على 3600 للحصول على الساعات. يعطي الباقي مقسوماً على 60 الدقائق. الباقي النهائي هو الثواني.

تضيف طريقة padStart() أصفاراً بادئة عندما تكون القيمة أقل من 10. يضمن هذا أن "5" تصبح "05" للحصول على تنسيق متسق.

بالنسبة للمدد المخزنة ككائنات مدة بدلاً من إجمالي الثواني، استخرج القيم مباشرة.

function formatDurationObject(duration) {
  const h = duration.hours || 0;
  const m = duration.minutes || 0;
  const s = duration.seconds || 0;

  if (h > 0) {
    return `${h}:${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`;
  }
  return `${m}:${String(s).padStart(2, '0')}`;
}

formatDurationObject({ hours: 1, minutes: 5, seconds: 30 }); // "1:05:30"
formatDurationObject({ minutes: 5, seconds: 30 }); // "5:30"

أضف الثواني الكسرية من خلال تضمين الميلي ثانية والتنسيق بدقة عشرية.

function formatWithMilliseconds(duration) {
  const m = duration.minutes || 0;
  const s = duration.seconds || 0;
  const ms = duration.milliseconds || 0;

  const paddedSeconds = String(s).padStart(2, '0');
  const fractional = String(ms).padStart(3, '0').slice(0, 2);

  return `${m}:${paddedSeconds}.${fractional}`;
}

formatWithMilliseconds({ minutes: 1, seconds: 23, milliseconds: 450 });
// "1:23.45"

تحقق من دعم واجهة برمجة التطبيقات قبل استخدامها.

function formatDuration(duration) {
  if (typeof Intl.DurationFormat !== 'undefined') {
    return new Intl.DurationFormat('en', { style: 'digital' }).format(duration);
  } else {
    return formatDurationObject(duration);
  }
}

يوفر هذا النهج مخرجات متسقة عبر جميع المتصفحات مع استخدام واجهة برمجة التطبيقات الأصلية عند توفرها.

الأنماط الشائعة لمشغلات الفيديو والمؤقتات

تحتاج مشغلات الفيديو إلى تنسيق كل من الوقت الحالي والمدة الإجمالية. أنشئ أداة تنسيق قابلة لإعادة الاستخدام للتعامل مع كلتا القيمتين.

const videoFormatter = new Intl.DurationFormat('en', { style: 'digital' });

function formatVideoPosition(currentSeconds, totalSeconds) {
  const current = secondsToDuration(currentSeconds);
  const total = secondsToDuration(totalSeconds);

  return `${videoFormatter.format(current)} / ${videoFormatter.format(total)}`;
}

function secondsToDuration(seconds) {
  const hours = Math.floor(seconds / 3600);
  const minutes = Math.floor((seconds % 3600) / 60);
  const secs = Math.floor(seconds % 60);

  return hours > 0
    ? { hours, minutes, seconds: secs }
    : { minutes, seconds: secs };
}

formatVideoPosition(125, 6345); // "2:05 / 1:45:45"

بالنسبة لمؤقتات العد التنازلي التي يتم تحديثها في كل إطار، أنشئ أداة التنسيق مرة واحدة وأعد استخدامها.

const timerFormatter = new Intl.DurationFormat('en', {
  style: 'digital',
  fractionalDigits: 2
});

function updateTimer(remainingMs) {
  const duration = {
    minutes: Math.floor(remainingMs / 60000),
    seconds: Math.floor((remainingMs % 60000) / 1000),
    milliseconds: remainingMs % 1000
  };

  document.getElementById('timer').textContent = timerFormatter.format(duration);
}

بالنسبة لساعات الإيقاف التي تعرض أوقات اللفات، قم بتنسيق الوقت المنقضي بالثواني الكسرية.

const lapFormatter = new Intl.DurationFormat('en', {
  style: 'digital',
  fractionalDigits: 3
});

function formatLapTime(startMs, endMs) {
  const elapsedMs = endMs - startMs;

  return lapFormatter.format({
    minutes: Math.floor(elapsedMs / 60000),
    seconds: Math.floor((elapsedMs % 60000) / 1000),
    milliseconds: elapsedMs % 1000
  });
}

const lap1Start = performance.now();
// ... time passes ...
const lap1End = performance.now();

formatLapTime(lap1Start, lap1End); // "1:23.456"

تتعامل هذه الأنماط مع سيناريوهات تنسيق المدة الأكثر شيوعاً مع الحفاظ على كود نظيف وقابل لإعادة الاستخدام.