Rrule: ارتباك التوقيت العالمي المنسق ولكن ليس التوقيت العالمي المتفق عليه (UTC)

تم إنشاؤها على ٥ أبريل ٢٠١٩  ·  18تعليقات  ·  مصدر: jakubroztocil/rrule

أظن أن هذه ليست مشكلة مع القاعدة ، ولكن مع فهمي لها و / أو دعم المنطقة الزمنية الخاصة بها. لقد قرأت بالفعل الأقسام ذات الصلة في وثائق " القاعدة" و " luxon" .

عينة التعليمات البرمجية

const { RRule, RRuleSet } = require(`rrule`);

const dtstart = new Date();
console.log(`dtstart`, dtstart);

const firstHour = dtstart.getHours();
const secondHour = (firstHour + 2) % 24;

const getRRule = options => new RRule(Object.assign({}, options, {
    freq: RRule.DAILY,
    count: 1,
    dtstart,
    byminute: 0,
    bysecond: 0
}));

const showNextInstance = tzid => {
    const ruleSet = new RRuleSet();
    ruleSet.rrule(getRRule({ tzid, byhour: firstHour }));
    ruleSet.rrule(getRRule({ tzid, byhour: secondHour }));
    console.log(tzid, ruleSet.after(dtstart));
};

showNextInstance(undefined);
showNextInstance(`UTC`);
showNextInstance(`local`);
showNextInstance(`America/Chicago`);

الناتج الحقيقي

dtstart 2019-04-05T11:51:23.744Z
undefined 2019-04-06T06:00:00.744Z
UTC 2019-04-06T06:00:00.744Z
local 2019-04-06T06:00:00.744Z
America/Chicago 2019-04-06T06:00:00.744Z

الناتج المتوقع

أعتقد أن تحديد tzid سيكون له بعض التأثير على المخرجات ، ولكن يتم إنشاء نفس الناتج لكل منطقة زمنية.

لا يمكنني أيضًا رؤية العلاقة بين الأوقات المنصوص عليها في القواعد والمخرجات الخاصة بمثيل الحدث التالي. أتوقع أن المثيل التالي سيتوافق تقريبًا مع إحدى الساعتين التي تمثلها القواعد المقدمة اعتمادًا على كيفية تفسير قيم dtstart و tzid أو تطبيقها.

إصدار القاعدة

2.6.0

نظام التشغيل

OS X 10.14.2 ، العقدة 8.11.4

المنطقة الزمنية المحلية

$ date
Fri Apr  5 06:32:33 CDT 2019

التعليق الأكثر فائدة

أعتقد أنه من السهل الخلط بين المشكلات مع الكائن Date ومشكلات حساب التكرارات لـ RRULE ، لذلك سأتحدث عنها بشكل منفصل قبل الجمع بين الاثنين. اضطررت إلى كتابة هذا في الغالب حتى أتمكن من فرز فهمي للمشكلة واكتشفت أنني سأقوم بنشرها هنا في حال كان ذلك يساعد الآخرين.

كائن تاريخ جافا سكريبت

لا أوافق على أن كائن JS Date غير منتظم ، ولكن هناك سوء فهم شائع مع الكائن الذي يجعله يبدو بهذه الطريقة. أقل ما يقال أنه محير.

كما ذكر @ hlee5zebra ، يتم دائمًا تمثيل التواريخ التي تم إنشاؤها باستخدام Date بالتوقيت العالمي المنسق. قد يتم عرضها بالتوقيت المحلي ، لكنها في الواقع ممثلة في وقت Unix Epoch خلف الكواليس. يمكننا دائمًا تشغيل .getTime() أو .toISOString() على الكائن Date لتذكير أنفسنا بأننا نعمل في UTC.

يتبع التنفيذ بشكل صحيح أيضًا اصطلاح إجراء جميع عمليات المعالجة بالتوقيت العالمي المنسق (UTC) والتحويل فقط إلى التوقيت المحلي المعروض للمستخدم. يحدث فقط أننا ، المطورين ، هم المستخدم ؛ ولكن بعد ذلك لدينا مستخدمنا الخاص بنا الذي يفسد المياه. عند تطوير تطبيقاتنا ، يجب أن نتأكد من اتباع الاتفاقية وحفظ التواريخ كـ UTC في الواجهة الخلفية لدينا (تقوم JS بالفعل بمعالجة التواريخ في UTC لذلك نحن جيدون هناك). إذا قمت بتخزين التواريخ كـ UTC في مخزن البيانات الخاص بك ، فيجب أن تصل إلى العميل كسلاسل ISO ، ويتم تحليلها بشكل صحيح بواسطة الكائن Date ، ويتم عرضها في التوقيت المحلي للمستخدم ، كل ذلك دون القيام بأي رفع ثقيل.

ساعدتني هذه الكتابة في فهم الكائن Date واكتشاف مقدار ما يمكنني فعله به: https://www.toptal.com/software/definitive-guide-to-datetime-manipulation

رد فعل

يصبح حساب التكرارات لـ RRULE أمرًا صعبًا نظرًا لوجود اختلاف جوهري في توقعات المستخدم ومعالجة التواريخ بالتوقيت العالمي المنسق (UTC) ، ويمكن ملاحظته عندما يعبر هذان التمثيلان الزمنيان حاجز اليوم.

على سبيل المثال ، إذا أراد مستخدمنا التكرار الذي يحدث كل ثلاثاء ، فسيتوقع أن تقع جميع الأحداث يوم الثلاثاء بالتوقيت المحلي. ومع ذلك ، تتم جميع العمليات الحسابية بالتوقيت العالمي المنسق ، لذلك فإن RRULE مثل:

DTSTART:2019-10-29T00:02:26Z
RRULE:FREQ=WEEKLY;BYWEEKDAY=TU

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

القيام بذلك بشكل صحيح

كل ما قيل ، ما يجب على المطور فعله لحل هذه المشكلة هو إجبار JavaScript على الاعتقاد بأن التاريخ المحلي هو في الواقع تاريخ UTC ، وإعطاء هذا التاريخ "الوهمي" إلى rrule.js ، وجعل المكتبة تجري حساباتها في هذا التوقيت المحلي UTC. عندما تحصل على التكرارات من طريقة .all() ، فإنك تقوم بإنشاء مثيل جديد للكائنات Date باستخدام أجزاء "التوقيت العالمي المنسق" من تلك التواريخ. هذا يجعل النتائج تتطابق بشكل فعال مع التوقعات.

import { RRule } from 'rrule'

const dtstart = new Date('2019-10-29T00:02:26Z') // same as: `new Date(Date.UTC(2019, 9, 29, 0, 2, 26))`
console.log(dtstart.toISOString()) // 2019-10-29T00:02:26.000Z
console.log(dtstart) // Mon Oct 28 2019 17:02:26 GMT-0700 (Pacific Daylight Time)

const fakeDateStart = setPartsToUTCDate(dtstart)
console.log(fakeDateStart.toISOString()) // 2019-10-28T17:02:26.000Z
console.log(fakeDateStart) // Mon Oct 28 2019 10:02:26 GMT-0700 (Pacific Daylight Time)

const rule = new RRule({
  freq: RRule.WEEKLY,
  byweekday: [RRule.TU],
  count: 2,
  dtstart: fakeDateStart
})

const localUTCOccurrences = rule.all()
console.log(localUTCOccurrences.map(toISOString)) // ["2019-10-29T17:02:26.000Z", "2019-11-05T17:02:26.000Z"]
console.log(localUTCOccurrences) // [Tue Oct 29 2019 10:02:26 GMT-0700 (Pacific Daylight Time), Tue Nov 05 2019 09:02:26 GMT-0800 (Pacific Standard Time)]

const occurrences = localUTCOccurrences.map(setUTCPartsToDate)
console.log(occurrences.map(toISOString)) // ["2019-10-30T00:02:26.000Z", "2019-11-06T01:02:26.000Z"]
console.log(occurrences) // [Tue Oct 29 2019 17:02:26 GMT-0700 (Pacific Daylight Time), Tue Nov 05 2019 17:02:26 GMT-0800 (Pacific Standard Time)]

function setPartsToUTCDate(d) {
  return new Date(
    Date.UTC(
      d.getFullYear(),
      d.getMonth(),
      d.getDate(),
      d.getHours(),
      d.getMinutes(),
      d.getSeconds()
    )
  )
}

function setUTCPartsToDate(d) {
  return new Date(
    d.getUTCFullYear(),
    d.getUTCMonth(),
    d.getUTCDate(),
    d.getUTCHours(),
    d.getUTCMinutes(),
    d.getUTCSeconds()
  )
}

function toISOString(d) {
  return d.toISOString()
}

https://codesandbox.io/s/rrule-localutc-conversion-zxlki

أو باختصار:

import { RRule } from 'rrule'

const date = new Date('2019-10-29T00:02:26Z')

const rule = new RRule({
  freq: RRule.WEEKLY,
  byweekday: [RRule.TU],
  count: 2,
  dtstart: setPartsToUTCDate(date)
})

const occurrences = rule.all().map(setUTCPartsToDate)

https://codesandbox.io/s/rrule-localutc-conversion-in-short-ez7g0

بقدر ما أستطيع أن أرى ، يعرض كل من Chrome و Firefox و Safari التواريخ كسلاسل بالتوقيت المحلي عند تسجيل الدخول إلى وحدة التحكم ، و Node.js كسلاسل ISO في UTC.

ال 18 كومينتر

أنا أيضا مرتبك بشكل رهيب.

حسنًا ، لقد فهمت ، كانت هناك هذه الفقرة الرئيسية في الملف التمهيدي:

image

يجب عليك استخدام هاتين الوظيفتين المساعدتين للمنطقة الزمنية المحلية. سيكون عليك تعديل الإزاحة للحصول على الإزاحة للمنطقة الزمنية X إذا كنت تريد تعديل هذا لدعم tzid.

/**
 * Mutates date. Add timezone to the date.
 *
 * <strong i="9">@param</strong> {Date} [date]
 */
export function localizeDate(date = new Date()) {
  const offset = new Date().getTimezoneOffset() * 60 * 1000; // get offset for local timezone (can modify here to support tzid)
  date.setTime(date.getTime() - offset);
  return date;
}

/**
 * Mutates a date. De-timezones a date.
 *
 * <strong i="10">@param</strong> {Date} [date]
 */
export function utcifyDate(date = new Date()) {
  const offset = new Date().getTimezoneOffset() * 60 * 1000; // get offset for local timezone (can modify here to support tzid)
  date.setTime(date.getTime() + offset);
  return date;
}

ثم سيتغير الرمز الخاص بك إلى:

const { RRule, RRuleSet } = require(`rrule`);

const dtstart = localizeDate(new Date());
console.log(`dtstart`, utcifyDate(new Date(dtstart))); // even though it is utc string, this is the local time

const firstHour = dtstart.getUTCHours();
const secondHour = (firstHour + 2) % 24;

const getRRule = options => new RRule(Object.assign({}, options, {
    freq: RRule.DAILY,
    count: 1,
    dtstart,
    byminute: 0,
    bysecond: 0
}));

const showNextInstance = tzid => {
    const ruleSet = new RRuleSet();
    ruleSet.rrule(getRRule({ byhour: firstHour })); // remove tzid as i dont support this
    ruleSet.rrule(getRRule({ byhour: secondHour })); // removed tzid as i dont support this
    console.log('local:', utcifyDate(ruleSet.after(dtstart));
};

showNextInstance(undefined);
showNextInstance(`UTC`);
showNextInstance(`local`);
showNextInstance(`America/Chicago`);

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

شكرا @ davidgoli عملك موضع تقدير كبير جدا !!!

أعتقد أننا بحاجة إلى شخص يفهم كتابة مقال لمساعدة الآخرين على فهم تنفيذ التاريخ غير النظامي. بصراحة ما زلت لا أفهم ذلك ، لقد قمت فقط بتعديل الأشياء حتى تعمل.

قد يرجع ذلك إلى أن التاريخ الذي تم إرجاعه الذي تطبعه على وحدة التحكم هو تاريخ JavaScript يتم تحويله إلى سلسلة ، وتقوم JavaScript تلقائيًا بطباعة التواريخ إلى وحدة التحكم بالتوقيت العالمي المنسق (انظر الحرف "Z" في نهاية الطوابع الزمنية الخاصة بك والتي تشير صفر تعويض). نظرًا لأن التكرارات التالية في كل حالة من الحالات الأربع تحدث في نفس الوقت بالضبط (على الرغم من وجودها في مناطق زمنية مختلفة) ، فإنها تطبع نفس الطابع الزمني بالضبط أربع مرات.

لاحظ أيضًا أن كائن JavaScript Date يتتبع الوقت باستخدام عدد المللي ثانية التي انقضت منذ 00:00:00 بالتوقيت العالمي المنسق ، الخميس ، 1 يناير 1970 (لاحظ "UTC" هناك!) ، وليس من قبل البعض نوع من تفسير السلسلة "12:34:56 مساءً" أو أي شيء من هذا القبيل.

تضمين التغريدة

أنا أعمل حاليًا على إعادة كتابة كاملة ، لكن الأمر سيستغرق بعض الوقت حتى يتم تصحيحها.

قد ترغب في التحقق من مصدر rSchedule . تتم جميع عمليات التكرار باستخدام كائن DateTime (وليس من Luxon) يأخذ مُدخلًا ويحوله إلى تاريخ utc عائم يبدو مكافئًا للإدخال. يتم إجراء التكرار باستخدام وقت التوقيت العالمي المنسق (UTC) ، لذا لا يمثل التوقيت الصيفي مشكلة. بعد العثور على حدث ما ، قبل إعادته إلى المستخدم ، يتم تحويله مرة أخرى إلى تاريخ عادي في المنطقة الزمنية المناسبة.

على سبيل المثال: هذا التاريخ

import { DateTime as LuxonDateTime } from 'luxon';

const date = LuxonDateTime.fromObject({
  year: 2019,
  month: 1,
  day: 1,
  zone: 'America/Los_Angeles'
})

سيتم تحويله إلى تاريخ UTC هذا وسيتم حفظ المنطقة الزمنية

const fakeDate = Date.UTC(2019, 0, 1)
const fakeDateZone = 'America/Los_Angeles'

لاحظ أن تاريخ UTC هذا يبدو مشابهًا لتاريخ Luxon (كلاهما يشبه 2019/1/1 ) ولكن نظرًا لوجودهما في مناطق زمنية مختلفة ، فإنهما لا يمثلان في الواقع نفس الوقت.

ومع ذلك ، فإن التكرار مع هذا التاريخ "UTC" الخاص يتيح لنا التكرار دون القلق بشأن التوقيت الصيفي. بعد العثور على التاريخ الصحيح ، يمكننا التحويل مرة أخرى إلى تاريخ luxon.

على سبيل المثال:

LuxonDateTime.fromObject({
  year: fakeDate.year,
  month: fakeDate.month,
  day: fakeDate.day,
  zone: fakeDateZone,
})

هذا يحافظ على منطق التكرار لطيفًا وصديقًا للتوقيت العالمي المنسق مع استمرار دعم المناطق الزمنية التعسفية.

thefliik لقد حصلت على الأوليات ؛ هذه الأسابيع هي الصداع الحقيقي هنا. على الرغم من أنني أرى أن rschedule قد قيل أيضًا (حتى الآن) على دعم byweekno & bysetpos ...

اه، نعم. byweekno مزعج للغاية.

أى اخبار؟

أعتقد أنه من السهل الخلط بين المشكلات مع الكائن Date ومشكلات حساب التكرارات لـ RRULE ، لذلك سأتحدث عنها بشكل منفصل قبل الجمع بين الاثنين. اضطررت إلى كتابة هذا في الغالب حتى أتمكن من فرز فهمي للمشكلة واكتشفت أنني سأقوم بنشرها هنا في حال كان ذلك يساعد الآخرين.

كائن تاريخ جافا سكريبت

لا أوافق على أن كائن JS Date غير منتظم ، ولكن هناك سوء فهم شائع مع الكائن الذي يجعله يبدو بهذه الطريقة. أقل ما يقال أنه محير.

كما ذكر @ hlee5zebra ، يتم دائمًا تمثيل التواريخ التي تم إنشاؤها باستخدام Date بالتوقيت العالمي المنسق. قد يتم عرضها بالتوقيت المحلي ، لكنها في الواقع ممثلة في وقت Unix Epoch خلف الكواليس. يمكننا دائمًا تشغيل .getTime() أو .toISOString() على الكائن Date لتذكير أنفسنا بأننا نعمل في UTC.

يتبع التنفيذ بشكل صحيح أيضًا اصطلاح إجراء جميع عمليات المعالجة بالتوقيت العالمي المنسق (UTC) والتحويل فقط إلى التوقيت المحلي المعروض للمستخدم. يحدث فقط أننا ، المطورين ، هم المستخدم ؛ ولكن بعد ذلك لدينا مستخدمنا الخاص بنا الذي يفسد المياه. عند تطوير تطبيقاتنا ، يجب أن نتأكد من اتباع الاتفاقية وحفظ التواريخ كـ UTC في الواجهة الخلفية لدينا (تقوم JS بالفعل بمعالجة التواريخ في UTC لذلك نحن جيدون هناك). إذا قمت بتخزين التواريخ كـ UTC في مخزن البيانات الخاص بك ، فيجب أن تصل إلى العميل كسلاسل ISO ، ويتم تحليلها بشكل صحيح بواسطة الكائن Date ، ويتم عرضها في التوقيت المحلي للمستخدم ، كل ذلك دون القيام بأي رفع ثقيل.

ساعدتني هذه الكتابة في فهم الكائن Date واكتشاف مقدار ما يمكنني فعله به: https://www.toptal.com/software/definitive-guide-to-datetime-manipulation

رد فعل

يصبح حساب التكرارات لـ RRULE أمرًا صعبًا نظرًا لوجود اختلاف جوهري في توقعات المستخدم ومعالجة التواريخ بالتوقيت العالمي المنسق (UTC) ، ويمكن ملاحظته عندما يعبر هذان التمثيلان الزمنيان حاجز اليوم.

على سبيل المثال ، إذا أراد مستخدمنا التكرار الذي يحدث كل ثلاثاء ، فسيتوقع أن تقع جميع الأحداث يوم الثلاثاء بالتوقيت المحلي. ومع ذلك ، تتم جميع العمليات الحسابية بالتوقيت العالمي المنسق ، لذلك فإن RRULE مثل:

DTSTART:2019-10-29T00:02:26Z
RRULE:FREQ=WEEKLY;BYWEEKDAY=TU

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

القيام بذلك بشكل صحيح

كل ما قيل ، ما يجب على المطور فعله لحل هذه المشكلة هو إجبار JavaScript على الاعتقاد بأن التاريخ المحلي هو في الواقع تاريخ UTC ، وإعطاء هذا التاريخ "الوهمي" إلى rrule.js ، وجعل المكتبة تجري حساباتها في هذا التوقيت المحلي UTC. عندما تحصل على التكرارات من طريقة .all() ، فإنك تقوم بإنشاء مثيل جديد للكائنات Date باستخدام أجزاء "التوقيت العالمي المنسق" من تلك التواريخ. هذا يجعل النتائج تتطابق بشكل فعال مع التوقعات.

import { RRule } from 'rrule'

const dtstart = new Date('2019-10-29T00:02:26Z') // same as: `new Date(Date.UTC(2019, 9, 29, 0, 2, 26))`
console.log(dtstart.toISOString()) // 2019-10-29T00:02:26.000Z
console.log(dtstart) // Mon Oct 28 2019 17:02:26 GMT-0700 (Pacific Daylight Time)

const fakeDateStart = setPartsToUTCDate(dtstart)
console.log(fakeDateStart.toISOString()) // 2019-10-28T17:02:26.000Z
console.log(fakeDateStart) // Mon Oct 28 2019 10:02:26 GMT-0700 (Pacific Daylight Time)

const rule = new RRule({
  freq: RRule.WEEKLY,
  byweekday: [RRule.TU],
  count: 2,
  dtstart: fakeDateStart
})

const localUTCOccurrences = rule.all()
console.log(localUTCOccurrences.map(toISOString)) // ["2019-10-29T17:02:26.000Z", "2019-11-05T17:02:26.000Z"]
console.log(localUTCOccurrences) // [Tue Oct 29 2019 10:02:26 GMT-0700 (Pacific Daylight Time), Tue Nov 05 2019 09:02:26 GMT-0800 (Pacific Standard Time)]

const occurrences = localUTCOccurrences.map(setUTCPartsToDate)
console.log(occurrences.map(toISOString)) // ["2019-10-30T00:02:26.000Z", "2019-11-06T01:02:26.000Z"]
console.log(occurrences) // [Tue Oct 29 2019 17:02:26 GMT-0700 (Pacific Daylight Time), Tue Nov 05 2019 17:02:26 GMT-0800 (Pacific Standard Time)]

function setPartsToUTCDate(d) {
  return new Date(
    Date.UTC(
      d.getFullYear(),
      d.getMonth(),
      d.getDate(),
      d.getHours(),
      d.getMinutes(),
      d.getSeconds()
    )
  )
}

function setUTCPartsToDate(d) {
  return new Date(
    d.getUTCFullYear(),
    d.getUTCMonth(),
    d.getUTCDate(),
    d.getUTCHours(),
    d.getUTCMinutes(),
    d.getUTCSeconds()
  )
}

function toISOString(d) {
  return d.toISOString()
}

https://codesandbox.io/s/rrule-localutc-conversion-zxlki

أو باختصار:

import { RRule } from 'rrule'

const date = new Date('2019-10-29T00:02:26Z')

const rule = new RRule({
  freq: RRule.WEEKLY,
  byweekday: [RRule.TU],
  count: 2,
  dtstart: setPartsToUTCDate(date)
})

const occurrences = rule.all().map(setUTCPartsToDate)

https://codesandbox.io/s/rrule-localutc-conversion-in-short-ez7g0

بقدر ما أستطيع أن أرى ، يعرض كل من Chrome و Firefox و Safari التواريخ كسلاسل بالتوقيت المحلي عند تسجيل الدخول إلى وحدة التحكم ، و Node.js كسلاسل ISO في UTC.

@ tim-phillips أنا أيضًا أعاني من هذا الآن وأبحث عن نوع من رقعة القرد للالتفاف حوله.

لدي حدث متكرر في الساعة 8 مساءً بتوقيت شرق الولايات المتحدة يعمل بشكل جيد ، ولكن 9 مساءً بتوقيت شرق الولايات المتحدة يعيده إلى اليوم السابق له.

نتطلع لمعرفة ما إذا كان يمكنك العثور على إجابة لهذا.

@ تيم فيليبس إنه تحليل ممتاز. ما زلت أمر به ، لكن يبدو أنه سيساعدني أخيرًا على الفهم ، شكرًا لك!

@ tim-phillips شكرًا لك على تحليلك.

ومع ذلك ، هل يمكنك شرح ما يلي؟ يبدو أن الحل الخاص بك لا يزال بإمكانه العودة يوم الأربعاء اعتمادًا على المنطقة الزمنية المحلية لجهاز الكمبيوتر الخاص بك.

image

tonylau لا تنظر إلى الإخراج المشدد في وحدة التحكم الخاصة بك ، والتي سيتم تحويلها دائمًا إلى منطقتك الزمنية المحلية. يجب عليك استخدام طرق getUTC*() للحصول على أجزاء التاريخ ، والتي ستكون هي نفسها بغض النظر عن منطقتك الزمنية المحلية.

تضمين التغريدة

لقد قمت بتعيين المنطقة الزمنية الخاصة بي على UTC + 14 (Kiritimati Island / Line Islands Time) وحصلت على ما يلي ، حتى عندما أستخدم getUTCDay (). لا يزال اليوم يعاد كأربعاء عندما يكون يوم الثلاثاء؟

Sandbox: https://codesandbox.io/s/rrule-localutc-conversion-in-short-0uzt1

image

يحتمل أن تكون ذات صلة بهذه المناقشة: https://github.com/tc39/proposal-temporal

@ تيم فيليبس شكرا !!!!!!!!!! كان ذلك مفيدًا جدًا !!!!!!! هل تعرف كيف تصنع ics مع القاعدة؟ أواجه مشكلة اليوم مرة أخرى عندما أستخدم حزمة ics في العقدة وعندما أتلقى دعوات التقويم ، يكونون يومًا إجازة. (لكنني قادر على وضع كل شيء في db الخاص بي بشكل صحيح بسبب الكود الخاص بك !! شكرًا جزيلاً.)

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات

القضايا ذات الصلة

grigio picture grigio  ·  7تعليقات

agordeev picture agordeev  ·  16تعليقات

marcoancona picture marcoancona  ·  22تعليقات

kirrg001 picture kirrg001  ·  5تعليقات

spurreiter picture spurreiter  ·  3تعليقات