معرفة ما إذا كان الوقت الحالي يقع في غضون مجموعة محددة من الوقت في اليوم الحالي في جافا

StackOverflow https://stackoverflow.com/questions/2473034

  •  20-09-2019
  •  | 
  •  

سؤال

أنا متأكد من أن هذا قد تم 1000 مرة في 1000 مكان مختلف. والسؤال هو أنني أريد أن أعرف ما إذا كانت هناك طريقة أفضل/قياسية/أسرع للتحقق مما إذا كان "الوقت" الحالي بين قيمتين من الوقت الوارد في hh:mm:ss صيغة. على سبيل المثال ، يجب ألا يعمل منطق العمل الكبير بين 18:00:00 and 18:30:00. إذن هذا ما كان يدور في ذهني:

 public static  boolean isCurrentTimeBetween(String starthhmmss, String endhhmmss) throws ParseException{
  DateFormat hhmmssFormat = new SimpleDateFormat("yyyyMMddhh:mm:ss");
  Date now = new Date();
  String yyyMMdd = hhmmssFormat.format(now).substring(0, 8);

  return(hhmmssFormat.parse(yyyMMdd+starthhmmss).before(now) &&
    hhmmssFormat.parse(yyyMMdd+endhhmmss).after(now));
 }

حالة اختبار مثال:

  String doNotRunBetween="18:00:00,18:30:00";//read from props file
  String[] hhmmss = downTime.split(",");
  if(isCurrentTimeBetween(hhmmss[0], hhmmss[1])){
   System.out.println("NOT OK TO RUN");
  }else{
   System.out.println("OK TO RUN");
  }

ما أبحث عنه هو رمز أفضل

  • في الأداء
  • في النظرات
  • في الصواب

ما لا أبحث عنه

  • مكتبات الطرف الثالث
  • استثناء معالجة النقاش
  • اتفاقيات تسمية متغيرة
  • القضايا تعديل الطريقة
هل كانت مفيدة؟

المحلول

هذا هو كل ما يجب عليك القيام به ، هذه الطريقة مقترنة بشكل فضفاض من المدخلات ومتماسكة للغاية.

boolean isNowBetweenDateTime(final Date s, final Date e)
{
    final Date now = new Date();
    return now.after(s) && now.before(e);
}

كيف تحصل على كائنات التاريخ للبدء والنهاية ليست ذات صلة بمقارنتها. أنت تجعل الأمور أكثر تعقيدًا مما تحتاج إلى المرور String تمثيلات حولها.

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

private Date dateFromHourMinSec(final String hhmmss)
{
    if (hhmmss.matches("^[0-2][0-9]:[0-5][0-9]:[0-5][0-9]$"))
    {
        final String[] hms = hhmmss.split(":");
        final GregorianCalendar gc = new GregorianCalendar();
        gc.set(Calendar.HOUR_OF_DAY, Integer.parseInt(hms[0]));
        gc.set(Calendar.MINUTE, Integer.parseInt(hms[1]));
        gc.set(Calendar.SECOND, Integer.parseInt(hms[2]));
        gc.set(Calendar.MILLISECOND, 0);
        return gc.getTime();
    }
    else
    {
        throw new IllegalArgumentException(hhmmss + " is not a valid time, expecting HH:MM:SS format");
    }
}

يمكنك الآن إجراء مكالمتين من الطريقة المسماة جيدًا والتي ستكون توثيقًا ذاتيًا.

نصائح أخرى

كما أشار كيفن ، لن تلتقط REGEX من Fuzzy Lollipop الأوقات بين الساعة 14:00 و 19:00.

للحصول على ساعة كاملة على مدار 24 ساعة ، يمكنك استخدام هذا:

if (hhmmss.matches("^([0-1][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$"))
{
    // Do stuff here
}

الفصل التالي هو شيء قمت بإنشائه للتو من بعض الكود من الإجابات الأخرى. إنه يلف سلوك "الفترة الزمنية" دون الارتباط بأيام محددة. يستخدم نظامنا هذه الفئة للتحقق مما إذا كان الوقت الحالي ضمن أحد نوافذ الصيانة المعينة. IE 05:00:00 - 07:00:00

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

/**
*
* @author Adam Yocum
*/
public class ExclusionTimePeriod {
    private String timeStart;
    private String timeEnd;

    /**
    * @return the timeStart
    */
    public String getTimeStart() {
        return timeStart;
    }

    /**
    * @param timeStart the timeStart to set
    */
    public void setTimeStart(String timeStart) {
        if (timeStart.matches("^([0-1][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$"))
        {
            this.timeStart = timeStart;
        }
        else
        {
            throw new IllegalArgumentException(timeStart + " is not a valid time, expecting HH:MM:SS format");
        }

    }

    /**
    * @return the timeEnd
    */
    public String getTimeEnd() {
        return timeEnd;
    }

    /**
    * @param timeEnd the timeEnd to set
    */
    public void setTimeEnd(String timeEnd) {
        if (timeEnd.matches("^([0-1][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$"))
        {
            this.timeEnd = timeEnd;
        }
        else
        {
            throw new IllegalArgumentException(timeEnd + " is not a valid time, expecting HH:MM:SS format");
        }
    }

    private Date toDate(String hhmmss){
        final String[] hms = hhmmss.split(":");
        final GregorianCalendar gc = new GregorianCalendar();
        gc.set(Calendar.HOUR_OF_DAY, Integer.parseInt(hms[0]));
        gc.set(Calendar.MINUTE, Integer.parseInt(hms[1]));
        gc.set(Calendar.SECOND, Integer.parseInt(hms[2]));
        gc.set(Calendar.MILLISECOND, 0);
        Date date = gc.getTime();
        return date;
    }

    public boolean isNowInPeriod()
    {
        final Date now = new Date();
        return now.after(toDate(getTimeStart())) && now.before(toDate(getTimeEnd()));
    }

    public static void main(String[] args){

        //Test All possible hours
        for(int hour=0;hour<=23;hour++){

            String hourStr = "";
            if(hour<=9){
                hourStr = "0"+hour;
            }else{
                hourStr = ""+hour;
            }

            for(int min=0;min<60;min++){
                String minStr = "";
                if(min<=9){
                    minStr = "0"+min;
                }else{
                    minStr = ""+min;
                }

                for(int sec=0;sec<60;sec++){
                    String secStr = "";
                    if(sec<=9){
                        secStr = "0"+sec;
                    }else{
                        secStr = ""+sec;
                    }

                    String hhmmss = hourStr+":"+minStr+":"+secStr;

                    ExclusionTimePeriod period = new ExclusionTimePeriod();
                    period.setTimeStart(hhmmss);
                    period.setTimeEnd(hhmmss);

                    System.out.println(hhmmss+" Ok");
                }
            }
        }


        //Test isInPeriod functionality
        ExclusionTimePeriod isInTest = new ExclusionTimePeriod();
        isInTest.setTimeStart("10:00:00");
        isInTest.setTimeEnd("10:43:00");

        System.out.println((new Date())+" is between "+isInTest.getTimeStart()+" and "+isInTest.getTimeEnd()+" = "+isInTest.isNowInPeriod());

    }
}

طريقة DateFromhourminsec معيب كما هو مكتوب. لن يسمح بأي ساعات حيث يكون رقم Seconde أكبر من 3 ، على سبيل المثال ، 18:00:00. إذا قمت بتغييره للسماح [0-2] [0-9] ، فسوف يسمح بأوقات مثل 29:00:00. هل لديك حل لذلك؟

TL ؛ د

LocalTime now = ZonedDateTime.now( ZoneId.of( "America/Montreal" ) )
                             .toLocalTime() ;
Boolean isBetween = ( ! now.isBefore( LocalTime.of( 18 , 0 ) )  // "not before" means "is equal to OR after".
                    && 
                    now.isBefore( LocalTime.of( 18 , 30 ) ) ;  // Half-Open, beginning is *inclusive* while ending is *exclusive*.

باستخدام java.time

أنت تستخدم فصول الوقت القديمة التي أثبتت أنها غير مصممة بشكل سيء ومربكة ومزعجة. وهم الآن إرث, ، حل محلها فصول Java.time.

LocalTime

لا تمر فقط الأوتار التي تمثل قيم وقت اليوم. لدينا الآن نوع لذلك ، LocalTime صف دراسي.

LocalTime start = LocalTime.of( 18 , 0 );
LocalTime stop = LocalTime.of( 18 , 30 );

تمرير هذه الحالات إلى طريقة فائدةك. لا ينبغي أن تضطر هذه الطريقة إلى القيام بأي تحليل ، لذلك لا داعي لرمي استثناء التحليل.

public static  boolean isCurrentTimeBetween( LocalTime start , LocalTime stop ) {
…

ZonedDateTime

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

حدد أ اسم المنطقة الزمنية المناسبة في شكل continent/region, ، مثل America/Montreal, Africa/Casablanca, ، أو Pacific/Auckland. لا تستخدم أبدًا اختصار 3-4 مثل EST أو IST كما هم ليس مناطق زمنية حقيقية ، غير موحدة ، ولا حتى فريدة من نوعها (!).

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.now( z );

لمقارنة وقت اليوم ، يمكننا ببساطة استخراج أ LocalTime من ذلك ZonedDateTime. لكن لدينا مشكلة الحالات الشاذة ، مثل وقت توفير النهار (DST) والسياسيون يعيدون تعريف المناطق الزمنية. قد لا يكون هناك الساعة 6 مساءً في تاريخ معين. يعتمد حل هذا اللغز على سياق عملك وقواعد عملك. يمكنك إما تجاهل اللغز والتمسك بحرارة تسأل ما إذا كان الوقت الحالي بين وقت بدء التشغيل المستهدف. أو يمكنك تطبيق المنطقة الزمنية على أوقات بدء اليوم ودعك ZonedDateTime الفصل إجراء تعديلات كما ترى مناسبة. دعونا نلقي نظرة على كلا النهجين.

تجاهل الحالات الشاذة

أولا ، تجاهل أي شذوذ. اسأل ببساطة وحرفيًا ما إذا كان الوقت الحالي للوقت الحالي بين البداية المستهدفة وتوقف أوقات اليوم.

يمكننا استخراج كائن من وقت اليوم من كائن تاريخ الموعد المحدد.

LocalTime localTimeNow = zdt.toLocalTime(); // Extract a time-of-day from the zoned date-time object.

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

Boolean isNowOnOrAfterStart = ( ! localTimeNow.isBefore( start ) ) ;  // A briefer way of asking "is equal to OR is after" is "is not before". 
Boolean isNowBeforeStop = localTimeNow.isBefore( stop );
Boolean isNowInTargetZone = ( isNowOnOrAfterStart && isNowBeforeStop ); // Half-Open: beginning is inclusive while ending is exclusive.

النظر في الحالات الشاذة

بعد ذلك نعتبر أي شذوذ. نطبق أوقات البدء والتوقف في اليوم على التاريخ الحالي في نفس المنطقة الزمنية. نقوم باستخراج التاريخ فقط من كائن تاريخ موعد.

LocalDate localDateToday = zdt.toLocalDate();
ZonedDateTime zdtStart = ZonedDateTime.of( localDateToday , start , z );
ZonedDateTime zdtStop = ZonedDateTime.of( localDateToday , stop , z );

دراسة الوثائق الفصل لفهم سلوك ZonedDateTime.of في حل قيم الوقت غير الصالحة في اليوم. لا توجد طريقة مثالية لحل قيم الوقت غير الموجودة في اليوم ، لذلك يجب عليك أن تقرر ما إذا كانت طريقة هذا الفصل تلبي قواعد عملك.

ZonedDateTime.of

public static ZonedDateTime of(LocalDate date, LocalTime time, ZoneId zone)

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

وقت التاريخ المحلي والمجتمع لأول مرة لتشكيل وقت محلي. ثم يتم حل وقت التاريخ المحلي إلى لحظة واحدة في الخط الزمني. يتم تحقيق ذلك من خلال إيجاد إزاحة صالحة من UTC/Greenwich لوقت التاريخ المحلي كما هو محدد في قواعد معرف المنطقة.

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

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

تطبيق نفس منطق المقارنة كما رأينا أعلاه.

Boolean isNowOnOrAfterStart = ( ! zdt.isBefore( zdtStart ) ) ;  // A briefer way of asking "is equal to OR is after" is "is not before". 
Boolean isNowBeforeStop = zdt.isBefore( zdtStop );
Boolean isNowInTargetZone = ( isNowOnOrAfterStart && isNowBeforeStop ); // Half-Open: beginning is inclusive while ending is exclusive.

طريقة بديلة لإجراء المقارنة هي استخدام المتناول Interval فئة من مشروع Threeten-Extra. هذا الفصل يأخذ ألم Instant الكائنات التي يمكنك استخلاصها من ZonedDateTime أشياء. ال Instant يمثل الفصل لحظة على الجدول الزمني في التوقيت العالمي بقرار نانو ثانية (حتى تسعة (9) أرقام من الكسر العشري).

Interval interval = Interval.of( zdtStart.toInstant() , zdtStop.toInstant() );
Boolean isNowInTargetZone = interval.contains( zdt.toInstant() );

حول java.time

ال Java.Time تم بناء إطار العمل في Java 8 وما بعده. هذه الفصول تحل محل القديم المزعج إرث فصول وقت التاريخ مثل java.util.Date, Calendar, & SimpleDateFormat.

ال وقت جودا مشروع ، الآن في نمط الصيانة, ، ينصح بالهجرة إلى Java.Time الطبقات.

لمعرفة المزيد ، انظر تعليمي أوراكل. والبحث في سعة مكدس للعديد من الأمثلة والتفسيرات. المواصفات JSR 310.

من أين تحصل على فصول java.time؟

ال Threeten-extra يمتد المشروع Java.time مع فصول إضافية. هذا المشروع هو أرضية إثبات للإضافات المستقبلية المحتملة إلى Java.time. قد تجد بعض الفصول المفيدة هنا مثل Interval, YearWeek, YearQuarter, ، و أكثر.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top