Getting time range between midnight and current time JDK 8 - date

I have this method to calculate midnigt and current time as long values:
/**
* Returns the time range between the midnight and current time in milliseconds.
*
* #param zoneId time zone ID.
* #return a {#code long} array, where at index: 0 - midnight time; 1 - current time.
*/
public static long[] todayDateRange(ZoneId zoneId) {
long[] toReturn = new long[2];
LocalTime midnight = LocalTime.MIDNIGHT;
LocalDate today = LocalDate.now(zoneId);
LocalDateTime todayMidnight = LocalDateTime.of(today, midnight);
ZonedDateTime todayMidnightZdt = todayMidnight.atZone(zoneId);
toReturn[0] = todayMidnightZdt.toInstant().toEpochMilli();
ZonedDateTime nowZdt = LocalDateTime.now().atZone(zoneId);
toReturn[1] = nowZdt.toInstant().toEpochMilli();
return toReturn;
}
Perhaps there is the simpler way to do that?

You could also do:
ZonedDateTime nowZdt = ZonedDateTime.now(zoneId);
ZonedDateTime todayAtMidnightZdt = nowZdt.with(LocalTime.MIDNIGHT);
I can't think of a simpler way to do it.
LocalDateTime vs ZonedDateTime
There's a (tricky) difference between LocalDateTime.now().atZone(zoneId) and ZonedDateTime.now(zoneId).
For the code below, I'm using a JVM in which the default timezone is America/Sao_Paulo and will try to get the current date and time in another timezone (Europe/London). At the moment I run this code, it's August 20th 2017, but in São Paulo the time is 17:56 and in London is 21:56.
When I do:
LocalDateTime nowLdt = LocalDateTime.now();
It creates a LocalDateTime with the current date and time in the JVM's default timezone. In this case, it'll get the current date and time in São Paulo's timezone (which is August 20th 2017, at 17:56):
2017-08-20T17:56:05.159
When I call the atZone method, it creates a ZonedDateTime that corresponds to this date and time in the specified zone:
ZoneId zoneId = ZoneId.of("Europe/London");
ZonedDateTime nowAtZone = nowLdt.atZone(zoneId);
The nowAtZone variable will be:
2017-08-20T17:56:05.159+01:00[Europe/London]
The same date (August 20th 2017) and time (17:56) in London timezone. Note that it's not the current date/time in London. If I get the equivalent epochMilli:
System.out.println(nowAtZone.toInstant().toEpochMilli());
It will be:
1503248165159
Now, if I don't use the LocalDateTime and direclty use the ZonedDateTime instead:
ZonedDateTime nowZdt = ZonedDateTime.now(zoneId);
It will get the current date and time in London, which will be:
2017-08-20T21:56:05.170+01:00[Europe/London]
Note that the time changed (it's 21:56). That's because right now, at this moment, that's the current time in London. If I get the epochMilli value:
System.out.println(nowZdt.toInstant().toEpochMilli());
The value will be:
1503262565170
Note that it's different from the first case using LocalDateTime (even if you ignore the difference in the milliseconds value, because the hour is different). If you want the current date and time at the specified timezone, you must use ZonedDateTime.now(zoneId).
Using LocalDateTime.now().atZone() not only gives a different result, but it will also change if you run in different JVM's, or if the JVM default timezone changes (someone might misconfigure it, or another application running in the same VM calls TimeZone.setDefault()).
Daylight Saving Time
Just remind about corner cases due to DST (Daylight Saving Time) issues. I'm gonna use the timezone I live in as example (America/Sao_Paulo).
In São Paulo, DST started at October 16th 2016: at midnight, clocks shifted 1 hour forward from midnight to 1 AM (and the offset changes from -03:00 to -02:00). So all local times between 00:00 and 00:59 didn't exist in this timezone (you can also think that clocks changed from 23:59:59.999999999 directly to 01:00). If I create a local date in this interval, it's adjusted to the next valid moment:
ZoneId zone = ZoneId.of("America/Sao_Paulo");
// October 16th 2016 at midnight, DST started in Sao Paulo
LocalDateTime d = LocalDateTime.of(2016, 10, 16, 0, 0, 0, 0);
ZonedDateTime z = d.atZone(zone);
System.out.println(z);// adjusted to 2017-10-15T01:00-02:00[America/Sao_Paulo]
When DST ends: in February 19th 2017 at midnight, clocks shifted back 1 hour, from midnight to 23 PM of 18th (and the offset changes from -02:00 to -03:00). So all local times from 23:00 to 23:59 existed twice (in both offsets: -03:00 and -02:00), and you must decide which one you want.
By default, it uses the offset before DST ends, but you can use the withLaterOffsetAtOverlap() method to get the offset after DST ends:
// February 19th 2017 at midnight, DST ends in Sao Paulo
// local times from 23:00 to 23:59 at 18th exist twice
LocalDateTime d = LocalDateTime.of(2017, 2, 18, 23, 0, 0, 0);
// by default, it gets the offset before DST ends
ZonedDateTime beforeDST = d.atZone(zone);
System.out.println(beforeDST); // before DST end: 2018-02-17T23:00-02:00[America/Sao_Paulo]
// get the offset after DST ends
ZonedDateTime afterDST = beforeDST.withLaterOffsetAtOverlap();
System.out.println(afterDST); // after DST end: 2018-02-17T23:00-03:00[America/Sao_Paulo]
Note that the dates before and after DST ends have different offsets (-02:00 and -03:00). This affects the value of epochMilli.
The above can also happen if you adjust the time using with method.

After modification the code now is much simpler:
/**
* Returns the time range between the midnight and current time in milliseconds.
*
* #param zoneId time zone ID.
* #return a {#code long} array, where at index: 0 - midnight time; 1 - current time.
*/
public static long[] todayDateRange(ZoneId zoneId) {
long[] toReturn = new long[2];
//ZonedDateTime nowZdt = LocalDateTime.now().atZone(zoneId);
ZonedDateTime nowZdt = ZonedDateTime.now(zoneId);//As suggested by Hugo (tested).
ZonedDateTime midZdt = nowZdt.with(LocalTime.MIDNIGHT);
toReturn[0] = midZdt.toInstant().toEpochMilli();
toReturn[1] = nowZdt.toInstant().toEpochMilli();
return toReturn;
}

Related

Date output is different.So,can't compare correctly

Here is my code.Please take a look first
import UIKit
var expireDate : Double = 1472647093
var date = NSDate(timeIntervalSince1970: expireDate)
print("Date : \(date)")
let current_date = NSDate()
if date.compare(current_date) == NSComparisonResult.OrderedDescending{
print("is Greater than current date")
}else if date.compare(current_date) == NSComparisonResult.OrderedAscending{
print("is Less than current date")
}else{
print("Same")
}
Here is the output on playground :
I really don't know why "Date : " output is different than date variable.My server send me an expire date format in unix timestamp which is long format.And I really need to compare it with current date.Actually
Aug 31, 2016, 7:08 PM // It has correct day/month/year but incorrect time
2016-08-31 12:38:13 +0000\n // has all correct time and date that the server send which was 12:38PM
So,why I am having greater than current date?And why it was 7:08PM instead of 12:38PM
Any help?
UPDATE :
You don't have wrong dates since Aug 31, 2016, 7:08 PM is your current timestamp, whereas in the print you have with timezone UTC. When you compare the dates they are both in UTC so you don't have any problems.
My above question has nothing wrong with it. I'm just misunderstood with the timezone or standard that I am dealing with. The server already send me expire date with my timezone locale in UTC standard format.
So,I don't need to change that expire date according to my current time zone.
All I have to do is get my current time,change it to UTC format using my current timezone. And compare server expire_date and current_date. Mission Accomplish.
// Using Expire Date
var expireDate : NSTimeInterval = 1472689452 // 00:24 AM UTC
var date = NSDate(timeIntervalSince1970: expireDate) // Since January 1 1970 Convert to NSDate
// Then I change this time format to UTC String without adding any timezone because its already included
var df_utc = NSDateFormatter()
df_utc.timeZone = NSTimeZone(name: "UTC")
df_utc.dateFormat = "yyyy.MM.dd G 'at' HH:mm:ss zzz"
// Get the expire date string by formatting it in UTC
var ts_utc_string : NSString = df_utc.stringFromDate(date)
// Getting current time of mine
var local_date = NSDate()
var df_local = NSDateFormatter()
df_local.timeZone = NSTimeZone(name: "MMT") // then use my locale to add that current time UTC [MMT +6:30]
df_local.dateFormat = "yyyy.MM.dd G 'at' HH:mm:ss zzz"
var ts_local_string : NSString = df_local.stringFromDate(local_date)
// Compare
if ts_local_string.compare(ts_utc_string as String) == NSComparisonResult.OrderedDescending{
print("CurrentTime is Greater than Expire Time")
}else if ts_local_string.compare(ts_utc_string as String) == NSComparisonResult.OrderedAscending{
print("CurrentTime is Less than Expire Time")
}else{
print("Same")
}
Here is the output :
For those who are still seeking for such problem like me, UTC was just a standard for timezone. If you need to compare it with your timezone, you just need to change your current time according to your country timezone.

AppleScript countdown

I want to have a string that counts down from current time to alarm time.
I've manage to figer out how to get the current time and how to set the alarm time.
The problem I'm having is that when I take current time - alarm time it gives me a numer witch I then need to format back to a hh:mm:ss string.
i've got this.
set alarmHour to 23
set alarmMinute to 00
set theDate to the current date
set the hours of theDate to alarmHour
set the minutes of theDate to alarmMinute
set the seconds of theDate to 0
theDate
set countdown to theDate - (current date)
set ss to countdown / 60
at this point it gives me 22.283333333333 witch i now need to convert to hh:mm:ss and then put them into a sting that give me 00:22:00
UPDATE:
in swift you have % you can use
countDownTime = (formatterInteger - timeControlInteger)
let interval = Int(countDownTime)
let seconds = interval % 60
let minutes = (interval / 60) % 60
let hours = (interval / 3600)
but how to you do this in applescript?
Answer to second question:
is there a way to format strings like in swift? like
String(format:"%02d",absHour) – Mathias Halén
Yes, but you need to use the Satimage.osax scripting addition, available for free at:
Satimage AppleScript Additions
Satimage strftime() -- Date/Time Format Function
strftime v : format a date using a specification string like in the C
function strftime.
strftime date or list of date
into string : the formatting string. To obtain ISO 8601 dates, use
"%FT%TZ" or "%GW%V-%uT%TZ" (using the 'with GMT' parameter)
[GMT boolean] : if true, output date as GMT. Default: false, the ouput
date is local.
→ string : the formatted date
EXAMPLE: strftime (current date) into “%x” RETURNS: 07/22/14
"%a, %b %d, %Y" RETURNS: Tue, Jul 22, 2014
set d to current date
-- some ISO 8601 formats:
strftime d into "%FT%T%z"
-- "2007-01-15T16:10:56+0100"
strftime d into "%GW%V-%uT%T%z"
-- "2007W03-1T16:10:56+0100"
--if you need to store the date d as UTC:
strftime d into "%FT%TZ" with GMT
-- "2007-01-15T15:10:56Z"
strftime d into "%a, %b %d, %Y %H:%M:%S %z"
-- "Mon, Jan 15, 2007 16:10:56 +0100"

How to convert an official DateTime to the astronomically exact DateTime?

I've been trying to figure out how to convert a birthday (DateTime) to the astronomically "exact" DateTime value. Timezone: UTC+1.
Example:
My friend was born 1984-01-27 11:35
1984 is a leap year. But 1700, 1800 and 1900 were not leap years. So until the 29. February of the year 2000 we are running behind in astronomoically exact time. In 1984 we are "almost" one day behind. So the astronomoically exact time would be after the official DateTime of my friend's birth, right?
These are the Gregorian calendar tweaks I know of:
Every year has 365 days
Every 4th year is a leap year (= has 366 days instead of 365)
Every 100th year is not a leap year
Every 400th year is a leap year (dispite the previous rule)
The additional day is added at the end of February (February has 29 days in a leap year)
Astronomoically a year has 365,2422 days.
Which means that a day is 24,0159254794 hours long.
A time value where the official and astronomoical times are "exactly" the same would be 2000-03-01T00:00:00, right?
So one would need to figure out how big the discrepancy between the official time and the astronomically exact time is at a given official time.
I've been thinking about it for hours, until my head started hurting. I figured I'll share my headache with you. Maybe you guys know any time library that can calculate this?
I came up with a "solution" that seems to be fairly accurate enough. Here's what it does:
The method starts at 1600-03-01T00:00. 18 years after Pope Gregor XIII. (after whom our Gregorian Calendar system is named) fixed the Julian Calendar (named after Julius Caesar) in 1582 by declaring that after the 4th October (Thursday) the next day would be the 15th October (Friday) - so there is actually no 5th to 14th October 1582 in history books - and also adding the 100th and 400th year rules to the calendar system.
The method sums up the discrepany between the official date and the exact date until the given date is reached.
At leap years it applies the correction added by Pope Gregor XIII. It does so at the end of February.
Code:
public static DateTime OfficialDateTimeToExactDateTime(DateTime dtOfficial)
{
const double dExactDayLengthInHours = 24.0159254794;
DateTime dtParse = new DateTime(1600, 3, 1, 0, 0, 0);
double dErrorInHours = 0.0;
while (dtParse <= dtOfficial)
{
dErrorInHours += dExactDayLengthInHours - 24;
dtParse = dtParse.AddDays(1);
if (dtParse.Month == 3 && dtParse.Day == 1 &&
((dtParse.Year % 4 == 0 && dtParse.Year % 100 != 0) ||
(dtParse.Year % 400 == 0)) )
{
dErrorInHours -= 24;
}
}
dErrorInHours += ((double)dtOfficial.Hour + (double)dtOfficial.Minute / 60 + (double)dtOfficial.Second / 3600) * (dExactDayLengthInHours - 24);
return dtOfficial.AddHours(dErrorInHours * -1);
}
I did some sanity testing:
If you pass a date before 2000-03-01T00:00 you get a negative correction. Because we measure days shorter as they in fact are.
If you pass a date after 2000-03-01T00:00 you get a positive correction. This is because 2000 is a leap year (while 1700, 1800 and 1900 are not), but the correction applied is too big. In 24 x 400 = 4800 years the correction would be about one day too big. So in the year 1600 + 4800 = 6400 (if man is still alive), you would need to delcare 6400 a non-leap year, despite the rules of the Gregorian calendar.

Calculate the current date from given seconds

You have been provided the current time as the number of seconds that have elapsed since the start of this century (i.e since the beginning of 2000) as input. You have to compute the date that the input time corresponds to.Note that the output required is an integer in yyyymmdd format where yyyy corresponds to year, mm to month and dd to date.
Note:without using array concept
Example:
currDate(122352353)=20031117 ( it corresponds to 17th November 2003).
long timeInMilliSecs = 122352353000L;
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("MMM dd yyyy");
try {
cal.setTime(sdf.parse("Jan 01 2000"));
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}// all done
long d = cal.getTimeInMillis() + timeInMilliSecs;
cal.setTimeInMillis(d);
System.out.println(cal.get(Calendar.YEAR) + "" + (cal.get(Calendar.MONTH)+1) + "" + cal.get(Calendar.DATE));
Always work with timeinmillis. This will help you easily convert any date. So first thing is convert your 2000 date to millis and add the given date(122352353 in this case) to it after converting to millis. That is it! Now just convert the milli time to date.

How do I convert microseconds into a timestamp?

I took this piece from an unencrypted .DAT file:
Code:
00 e1 27 17 6f e6 69 c0
Which translates to 63,374,851,375,000,000 in decimal. The units for the number are microseconds.
And this huge number cannot bypass the 1st January 1970 00:00:00 format; such a format that most converters use today.
So, yes. Is there such a converter that uses the 1st January of the year 1 format? Or how shall I make one?
And by the way, a timestamp is both date and time.
Thanks in advance!
You do not say what language are you using, if it is a .NET language, you can use: http://msdn.microsoft.com/en-us/library/z2xf7zzk.aspx for that constructor the input is in nanoseconds (are you sure that your number is in milliseconds and not in nanoseconds?).
If you are sure it is in milliseconds, the conversion to nanoseconds should be easy: 1 millisecond = 1 000 000 nanoseconds.
But I have the feeling that those are nanoseconds and not milliseconds...
Now that you have told us that it is in microseconds:
C# Example from decimal to yyyy dd MM hh:mm:ss
long microseconds = 63370738175000000;
long ticks = microseconds * 10;
DateTime timestamp = new DateTime(ticks);
Console.WriteLine(timestamp.ToString("yyyy dd MM hh:mm:ss"));
It prints:
2009 20 02 02:49:35
The other way around from yyyy dd MM hh:mm:ss to decimal
String dateString = "2009 20 02 02:49:35";
DateTime timestamp = DateTime.ParseExact(dateString, "yyyy dd MM hh:mm:ss",CultureInfo.CurrentCulture);
long ticks = timestamp.Ticks;
long microseconds = ticks / 10;
Console.WriteLine(microseconds);
It prints:
63370694975000000
And if you want it in hexadecimal just write:
Console.WriteLine(microseconds.ToString("X"));
Then it will print:
E1234FB3278DC0
If you want the answer in another programming language, please add that to you question.
In JAVA in order to convert microseconds into java.sql.Timestamp:
public static Timestamp getTimestampFromMicros(long pMicros) {
long millis = TimeUnit.MICROSECONDS.toMillis(pMicros);
long shaaritInMicros = pMicros - TimeUnit.MILLISECONDS.toMicros(millis);
Timestamp ts = new Timestamp(millis);
long nanos = ts.getNanos() + TimeUnit.MICROSECONDS.toNanos(shaaritInMicros);
ts.setNanos((int)nanos);
return ts;
}
Use below Java code to covert microseconds to date and time,
long msec = microseconds * 1/1000;
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
dateFormat.format(msec);
Which will returns,
2016-01-27 03:41:12