0

I want to get the time of a day in milliseconds, I do not this day to have any specific date, just a time. I made something, thought it worked, but then went debugging and concluded that it doesn't work how I want it to.

I want to use this to check if the current time is between both my specified startTime and endTime.

    long startTime = settings.getLong("startTime", 0);
    long endTime = settings.getLong("endTime", 0);

    if ((currentTime.getMillis() >= startTime)
            && (currentTime.getMillis() <= endTime)) {
            //Do stuff here

 }

How I am setting the time of the propeties startTime and endTime:

                        Calendar startTime = Calendar.getInstance();
                        startTime.set(Calendar.HOUR_OF_DAY, 16);
                        startTime.set(Calendar.MINUTE, 00);
                        editor.putLong("startTime",
                                startTime.getTimeInMillis());

                        Calendar endTime = Calendar.getInstance();
                        endTime.set(Calendar.HOUR_OF_DAY, 16);
                        endTime.set(Calendar.MINUTE, 00);
                        endTime.add(Calendar.HOUR_OF_DAY, 11);
                        editor.putLong("endTime",
                                endTime.getTimeInMillis());
                        editor.commit();

However this will mean that both startTimeand endTime will have this a specific date attached to it.

I hope I explained it well, any help is appreciated!

Jef
  • 791
  • 1
  • 18
  • 36
  • Why is it important to only have the millis of the day, if all you want is to compare the values? – Oliver Jan Krylow Mar 10 '14 at 02:36
  • This question was asked at a critical time, in the same month that Java 8 came out and with it `java.time`, the modern Java date and time API. Since then I recommend that no on uses the old `Calendar` class because it was always poorly designed. Use java.time and it `LocalTime` class. – Ole V.V. Aug 25 '21 at 15:55
  • 1
    Don’t use double-digit minutes like `00` in your Java code. You may find that it looks nice, but you will get an unpleasant surprise when `08` and `09` do not work for 8 and 9 minutes past the hour because numbers with a leading zero are interpreted as [oxtal numbers](https://en.wikipedia.org/wiki/Octal). – Ole V.V. Aug 27 '21 at 20:42

6 Answers6

2

Avoid Milliseconds

No need to mess with milliseconds for your purpose. Using milliseconds for date-time is confusing and error-prone.

What you need is a decent date-time library rather than the notoriously troublesome bundled java.util.Date & .Calendar classes.

Joda-Time

If you are certain you want to ignore dates and ignore time zones, here's some example code using the LocalTime class offered by the third-party free-of-cost Joda-Time library.

LocalTime start = new LocalTime( 10, 0, 0 );
LocalTime stop = new LocalTime( 14, 30, 0 );
LocalTime target = LocalTime.now();
boolean isNowInSpan = !( ( target.isBefore( target ) ) | ( target.isAfter( stop ) ) );

Adjust that last line according to your business logic needs. You might want:

  • The beginning and ending are inclusive
  • The beginning and ending are exclusive
  • "Half-Open" where the beginning is inclusive and the ending is exclusive
    (usually best for date-time work)

Dump to console…

System.out.println( "start: " + start );
System.out.println( "stop: " + stop );
System.out.println( "target: " + target );
System.out.println( "isNowInSpan: " + isNowInSpan );

When run…

start: 10:00:00.000
stop: 14:30:00.000
target: 23:49:37.779
isNowInSpan: false

Another Example

Time-of-day-only is not usually the right way to go. When new to date-time work, a naïve programmer may at first think that time-only simplifies things. On the contrary, this example shows how spinning around the clock creates complications. Using date+time+timeZone is usually the best approach in the long run.

LocalTime now = LocalTime.now();
LocalTime start = new LocalTime( 13, 0, 0, 0 );
LocalTime stop = start.plusHours( 11 );

System.out.println( "now: " + now );
System.out.println( "start: " + start );
System.out.println( "stop: " + stop );

if ( now.isAfter( start ) ) {
    System.out.println( "After start" );
}

if ( now.isBefore( stop ) ) {
    System.out.println( "Before stop" );
}

When run…

now: 14:00:32.496
start: 13:00:00.000
stop: 00:00:00.000
After start

java.time

Java 8 brings the new java.time package, inspired by Joda-Time, defined by JSR 310.

In java.time, you will find a LocalTime class similar to the one in Joda-Time.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • Thanks mate, I am going to try this right now! I have used Jodatime before and liked it quite well, thought I wouldn't need an additional library but this seems the best option. – Jef Mar 10 '14 at 17:18
  • @Jef Adding [Joda-Time](http://www.joda.org/joda-time/) is the first thing I do to any new project. Second thing is add [SLF4J](http://www.slf4j.org/) & [LogBack](http://logback.qos.ch/) for logging. – Basil Bourque Mar 10 '14 at 17:22
  • Thanks for your help, I am having some problems with implementing .isBefore(now). `currentTime = LocalTime.now(); startTime = new LocalTime( 13, 00, 0, 0); endTime = startTime.plusHours(11); if(currentTime.isAfter(startTime)){ Log.v("HydraService", "After startTime"); } if(currentTime.isBefore(endTime)){ Log.v("HydraService", "Before endTime"); }` `isAfter` is getting logged, but `isBefore` isn't, do you know why this is? – Jef Mar 10 '14 at 19:37
  • You are running into the limitations of using time-only, without dates and without time zones. Day-of-time-only is not usually what folks truly need, though naïve programmers may think so at first. That's why my answer said: `If you are certain you want to ignore dates and ignore time zones`. To answer your question, a hint: What is the result of ( 13 + 11 )? – Basil Bourque Mar 10 '14 at 20:58
  • Thanks for your input, I have made another question and a user made the same point as you. He gave me a solution which works, so this my previous question is irrelevant. – Jef Mar 10 '14 at 21:47
  • Link to Jef's related question, [JodaTime - Check if LocalTime is after now and now before another LocalTime](http://stackoverflow.com/q/22310329/642706). – Basil Bourque Mar 10 '14 at 22:47
2

A new approach with Java 8 onward.

int millisecondsOfDay = LocalTime.now().get(ChronoField.MILLI_OF_DAY);

Reference: https://o7planning.org/13669/java-localtime#a64448233

logbasex
  • 1,688
  • 1
  • 16
  • 22
1

Time without Date is meaning less. In Java timestamp it's using the Unix UTC and the timestamp start 0 on 01/01/1970. So, you startTime/endTime.getTimeInMillis() tell you the time different from UTC. Which mean your midnight is your base and your endTime.getTimeInMillis() will be the offset.

  Calendar cal = Calendar.getInstance();
  // set to mid-night
  cal.set(Calendar.HOUR_OF_DAY, 0);
  cal.set(Calendar.MINUTE, 0);
  cal.set(Calendar.SECOND, 0);
  cal.set(Calendar.MILLISECOND, 0);
  long midnight = cal.getTimeInMillis();

  cal.set(Calendar.HOUR_OF_DAY, 16);
  cal.set(Calendar.MINUTE, 00);
  long startTime = cal.getTimeInMillis();
  editor.putLong("startTime", (startTime - midnight));

  cal.add(Calendar.HOUR_OF_DAY, 11);
  long endTime = cal.getTimeInMillis();
  editor.putLong("endTime", (endTime - midnight));
  editor.commit();
TA Nguyen
  • 453
  • 1
  • 3
  • 8
  • Thank you for pointing this out, it makes sense now. When I wrote the code it worked, but when I changed some values it wouldn't work until next day. – Jef Mar 10 '14 at 17:01
1

Take a look at the Java 8 Time API. http://download.java.net/jdk8/docs/api/java/time/LocalTime.html#toNanoOfDay--

Oliver Jan Krylow
  • 1,758
  • 15
  • 22
  • It’s a good idea, though a link is very little for an answer. It would have fit better in a comment. – Ole V.V. Aug 24 '21 at 19:01
1

In case what you need is to get how many milliseconds since the start of this day and you have now in milliseconds you can get the milliseconds you want as simple as this

val nowMilliSeconds = System.currentTimeMillis() % 86400000

Where 86400000 is the number of milliseconds in a day so you will just get the remainder

atabouraya
  • 3,233
  • 1
  • 26
  • 31
1

java.time.LocalTime

I recommend that you use java.time, the modern Java date and time API, for your time work. Use a LocalTime object for time of day (it’s what it’s for).

    LocalTime time = LocalTime.of(16, 0);
    System.out.println(time);

Output:

16:00

If you cannot store a LocalTime object in your settings, convert to a string for human readability (a great advantage in debugging and support cases):

    String timeString = time.toString();
    LocalTime parsedBack = LocalTime.parse(timeString);
    System.out.println(parsedBack);

16:00

To answer the question as asked, in case you need to, converting to milliseconds is straightforward (when you know how):

    int milliOfDay = time.get(ChronoField.MILLI_OF_DAY);
    System.out.println(milliOfDay);

57600000

The milliseconds too can be converted back to a LocalTime object:

    LocalTime recreatedLocalTime
            = LocalTime.MIN.with(ChronoField.MILLI_OF_DAY, milliOfDay);
    System.out.println(recreatedLocalTime);

16:00

Link

Oracle tutorial: Date Time explaining how to use java.time.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161