Using NSDate to get date for Easter - swift

I'm working on an application that requires the use of getting dates for national holidays.
Below, I was able to get Memorial Day:
// Set the components for Memorial Day (last Monday of May)
let memorialDayComps = NSDateComponents()
memorialDayComps.weekday = 2
memorialDayComps.month = 5
memorialDayComps.year = currentYear
var mondaysOfMay = [NSDate]()
for var i = 1; i <= 5; i++ {
memorialDayComps.weekdayOrdinal = i
let monday = calendar.dateFromComponents(memorialDayComps)
let components = calendar.components(.CalendarUnitMonth, fromDate: monday!)
if components.month == 5 {
mondaysOfMay.append(monday!)
}
}
let memorialDayDate = mondaysOfMay.last
Because the dates are pretty well set, I am able to successfully create NSDate instances for the following holidays:
New Year's Day
Martin Luther King, Jr. Day
Presidents' Day
Memorial Day
Independence Day
Labor Day
Thanksgiving Day
Christmas Day
However, the only one that I am having difficulty figuring out how to get is Easter. It varies every year, so I'm curious as to whether anyone else has been able so successfully get the date for Easter via an API or other means.

I was able to find a gist on GitHub that has a solution that was accurate for calculating and returning an NSDate for Easter.
The code below is what the gist contains:
// Easter calculation in swift after Anonymous Gregorian algorithm
// Also known as Meeus/Jones/Butcher algorithm
func easter(Y : Int) -> NSDate {
let a = Y % 19
let b = Int(floor(Double(Y) / 100))
let c = Y % 100
let d = Int(floor(Double(b) / 4))
let e = b % 4
let f = Int(floor(Double(b+8) / 25))
let g = Int(floor(Double(b-f+1) / 3))
let h = (19*a + b - d - g + 15) % 30
let i = Int(floor(Double(c) / 4))
let k = c % 4
let L = (32 + 2*e + 2*i - h - k) % 7
let m = Int(floor(Double(a + 11*h + 22*L) / 451))
let components = NSDateComponents()
components.year = Y
components.month = Int(floor(Double(h + L - 7*m + 114) / 31))
components.day = ((h + L - 7*m + 114) % 31) + 1
components.timeZone = NSTimeZone(forSecondsFromGMT: 0)
let cal = NSCalendar(calendarIdentifier: NSGregorianCalendar)
return cal.dateFromComponents(components)
}
println(easter(2014)) // "2014-04-20 00:00:00 +0000"

That Easter algorithm works great!
Using with Swift 4.0 and pattern matching. Pattern matching made it easier for me to add other days based on month, day, weekday, weekdayOrdinal.
extension Date {
var isUSHoliday: Bool {
let components = Calendar.current.dateComponents([.year, .month, .day, .weekday, .weekdayOrdinal], from: self)
guard let year = components.year,
let month = components.month,
let day = components.day,
let weekday = components.weekday,
let weekdayOrdinal = components.weekdayOrdinal else { return false }
let easterDateComponents = Date.dateComponentsForEaster(year: year)
let easterMonth: Int = easterDateComponents?.month ?? -1
let easterDay: Int = easterDateComponents?.day ?? -1
let memorialDay = Date.dateComponentsForMemorialDay(year: year)?.day ?? -1
// weekday is Sunday==1 ... Saturday==7
// weekdayOrdinal is nth instance of weekday in month
switch (month, day, weekday, weekdayOrdinal) {
case (1, 1, _, _): return true // Happy New Years
case (1, 0, 2, 3): return true // MLK - 3rd Mon in Jan
case (2, 0, 2, 3): return true // Washington - 3rd Mon in Feb
case (easterMonth, easterDay, _, _): return true // Easter - rocket science calculation
case (5, memorialDay, _, _): return true // Memorial Day
case (7, 4, _, _): return true // Independence Day
case (9, 0, 2, 1): return true // Labor Day - 1st Mon in Sept
case (10, 0, 2, 2): return true // Columbus Day - 2nd Mon in Oct
case (11, 11, _, _): return true // Veterans Day
case (11, 0, 5, 4): return true // Happy Thanksgiving - 4th Thurs in Nov
case (12, 25, _, _): return true // Happy Holidays
case (12, 31, _, _): return true // New years Eve
default: return false
}
}
static func dateComponentsForMemorialDay(year: Int) -> DateComponents? {
guard let memorialDay = Date.memorialDay(year: year) else { return nil }
return NSCalendar.current.dateComponents([.year, .month, .day, .weekday, .weekdayOrdinal], from: memorialDay)
}
static func memorialDay(year: Int) -> Date? {
let calendar = Calendar.current
var firstMondayJune = DateComponents()
firstMondayJune.month = 6
firstMondayJune.weekdayOrdinal = 1 // 1st in month
firstMondayJune.weekday = 2 // Monday
firstMondayJune.year = year
guard let refDate = calendar.date(from: firstMondayJune) else { return nil }
var timeMachine = DateComponents()
timeMachine.weekOfMonth = -1
return calendar.date(byAdding: timeMachine, to: refDate)
}
static func easterHoliday(year: Int) -> Date? {
guard let dateComponents = Date.dateComponentsForEaster(year: year) else { return nil }
return Calendar.current.date(from: dateComponents)
}
static func dateComponentsForEaster(year: Int) -> DateComponents? {
// Easter calculation from Anonymous Gregorian algorithm
// AKA Meeus/Jones/Butcher algorithm
let a = year % 19
let b = Int(floor(Double(year) / 100))
let c = year % 100
let d = Int(floor(Double(b) / 4))
let e = b % 4
let f = Int(floor(Double(b+8) / 25))
let g = Int(floor(Double(b-f+1) / 3))
let h = (19*a + b - d - g + 15) % 30
let i = Int(floor(Double(c) / 4))
let k = c % 4
let L = (32 + 2*e + 2*i - h - k) % 7
let m = Int(floor(Double(a + 11*h + 22*L) / 451))
var dateComponents = DateComponents()
dateComponents.month = Int(floor(Double(h + L - 7*m + 114) / 31))
dateComponents.day = ((h + L - 7*m + 114) % 31) + 1
dateComponents.year = year
guard let easter = Calendar.current.date(from: dateComponents) else { return nil } // Convert to calculate weekday, weekdayOrdinal
return Calendar.current.dateComponents([.year, .month, .day, .weekday, .weekdayOrdinal], from: easter)
}
}

Here is a Swift 5 implementation of O'Beirne's algorithm with inline documentation.
The code is more compact than the implementations in the other provided answers because it makes use of Integer arithmetic and thus removes the need to explicitly round numbers and convert between Floats and Ints.
/// **How ten divisions lead to Easter** *by T. H. O'Beirne, New Scientist, march 30 1961 - Vol. 9,Nr. 228*
func easter(in year: Int) -> (day: Int, month: Int) {
/// Identify the position of the `year` in a 19-year cycle, to use this later to determine the principal constituent of the changes of full-moon dates from year to year
let a = year % 19
/// Take note of the corrections which the Gregorian calendar introduces in century years
let (b, c) = year.quotientAndRemainder(dividingBy: 100)
/// Take account of the leap-year exceptions in century years
let (d, e) = b.quotientAndRemainder(dividingBy: 4)
/// Provide similarly for the century years auxiliary corrections to the new-moon and full-moon dates
let g = (8*b + 13) / 25
/// Determine the number of days between 21 March and the coincident or next full moon, if no special exceptions arise
let h = (19*a + b - d - g + 15) % 30
/// Determine the position of the year in the ordinary leap-year cycle of four years
let (i, k) = c.quotientAndRemainder(dividingBy: 4)
/// Determine number of days (between 0 and 6) until the Sunday *after* full moon
let l = (2*e + 2*i - h - k + 32) % 7
/// The exceptions which make a 29-day month interrupt the regularity of a simpler pattern need here be considered *only* when they transfer the full moon *from a Sunday to a Saturday*: the *Easter date* is unaffected in other cases. When appropriate — 1954 and 1981 are quite rare examples — we have m=1; otherwise m=0 : this permits the necessary correction (failing which the Easter date *would* be 26 April in 1981.
let m = (a + 11*h + 19*l) / 433
/// Determine days between March 22 and Easter
let relativeDayCount = h + l - 7*m
/// Convert relative day count into absolute month and day index
let month = (relativeDayCount + 90) / 25
return (day: (relativeDayCount + 33*month + 19) % 32, month)
}
func easterDate(in year: Int) -> Date {
let (day, month) = easter(in: year)
let components = DateComponents(
timeZone: TimeZone(secondsFromGMT: 0),
year: year, month: month, day: day
)
return Calendar(identifier: .gregorian).date(from: components)!
}

Swift 4:
func easter(Y : Int) -> Date {
let a = Y % 19
let b = Int(floor(Double(Y) / 100))
let c = Y % 100
let d = Int(floor(Double(b) / 4))
let e = b % 4
let f = Int(floor(Double(b+8) / 25))
let g = Int(floor(Double(b-f+1) / 3))
let h = (19*a + b - d - g + 15) % 30
let i = Int(floor(Double(c) / 4))
let k = c % 4
let L = (32 + 2*e + 2*i - h - k) % 7
let m = Int(floor(Double(a + 11*h + 22*L) / 451))
var components = DateComponents()
components.year = Y
components.month = Int(floor(Double(h + L - 7*m + 114) / 31))
components.day = ((h + L - 7*m + 114) % 31) + 1
components.timeZone = TimeZone(secondsFromGMT: 0)
return Calendar.autoupdatingCurrent.date(from: components)!
}
print(easter(Y: 2018)) // "2018-04-01 00:00:00 +0000"

OBJECTIVE-C!
-(void) easterMonthAndDayForYear: (NSInteger) Y {
NSInteger a = Y % 19;
NSInteger b = (int) (floor( ((double)Y) / 100.0));
NSInteger c = Y % 100;
NSInteger d = (int)(floor(((double)b) / 4.0));
NSInteger e = b % 4;
NSInteger f = (int)(floor(((double)(b+8)) / 25.0));
NSInteger g = (int)(floor(((double)(b-f+1)) / 3.0));
NSInteger h = (19*a + b - d - g + 15) % 30;
NSInteger i = (int)(floor(((double)c) / 4.0));
NSInteger k = c % 4;
NSInteger L = (32 + 2*e + 2*i - h - k) % 7;
NSInteger m = (int)(floor(((double)(a + 11*h + 22*L)) / 451.0));
NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear |NSCalendarUnitTimeZone fromDate:[NSDate date]];
components.year = Y;
components.month = (int)(floor((double)(h + L - 7*m + 114) / 31.0));
components.day = ((h + L - 7*m + 114) % 31) + 1;
components.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
self.easterDayCache[#(Y)] = #{#"month": #(components.month), #"day":#(components.day)
};

Related

Convert decimal time to hours and minutes in Swift

I am new to programming and this is my first program and question. I'm trying to write a function which will simply convert decimal time to Hours & Minutes. I'm removing the hours and multiplying the decimal minutes by 60 and adding the two back together as a string. I need to use this facility a couple of times in my program hence the function. The calculation which uses this function is straightforward but I'm getting odd results. If I maintain 'plannedStartFuel' as 450 and adjust 'minLandAllowance' I get the following results,
185 returns 1:28
182 returns 1:29
181 returns 1:30
180 returns 2:30
179 returns 2:30
175 returns 2:32
The correct answers are the 1:00 figures. I don't understand why the program seems to add an hour to the results at the 180 point. I'm sure there are are far better ways of completing this calculation than I've used, but if you can help I'd be grateful to know which part is causing the error and why. What have I tried?...everything! If you pitch your answer at a 7 year old I may have a chance of understanding. Thank you.
import UIKit
import Foundation
func decimalHoursConv (hours : Double) -> (_hrs:String, mins:String) {
let remainder = hours.truncatingRemainder(dividingBy: 1) * 60
let mins = (String(format: "%.0f", remainder))
let hrs = (String(format: "%.0f", hours))
return (hrs, mins)
}
var plannedStartFuel = Double (0)
var minLandAllowance = Double (0)
var flyingTimeToMLA = Double(0)
plannedStartFuel = 450
minLandAllowance = 180
flyingTimeToMLA = ((plannedStartFuel - minLandAllowance) / 3)/60
let MLAtime = (decimalHoursConv(hours: flyingTimeToMLA))
print ("Flight Time To MLA =", MLAtime.0,"hrs",MLAtime.1,"mins")
I might advise not bothering to calculate hours and minutes at all, but rather let DateComponentsFormatter do this, creating the final string for you.
For example:
let formatter: DateComponentsFormatter = {
let formatter = DateComponentsFormatter()
formatter.unitsStyle = .full
formatter.allowedUnits = [.hour, .minute]
return formatter
}()
Then supply this formatter the elapsed time measured in seconds (a TimeInterval, which is just an alias for Double):
let remaining: TimeInterval = 90 * 60 // e.g. 90 minutes represented in seconds
if let result = formatter.string(from: remaining) {
print(result)
}
On a English speaking device, that will produce:
1 hour, 30 minutes
The virtue of this approach is that not only does it get you out of the business of manually calculating hours and minutes yourself, but also that the result is easily localized. So, if and when you get around to localizing your app, this string will be localized automatically for you, too, with no further work on your part. For example, if you add German to your app localizations, then the US user will still see the above, but on a German device, it will produce:
1 Stunde und 30 Minuten
If you want it to say how much time is remaining, set includesTimeRemainingPhrase:
let formatter: DateComponentsFormatter = {
let formatter = DateComponentsFormatter()
formatter.unitsStyle = .full
formatter.includesTimeRemainingPhrase = true
formatter.allowedUnits = [.hour, .minute]
return formatter
}()
That will produce:
1 hour, 30 minutes remaining
If you want a “hh:mm” sort of representation:
let formatter: DateComponentsFormatter = {
let formatter = DateComponentsFormatter()
formatter.unitsStyle = .positional
formatter.zeroFormattingBehavior = .pad
formatter.allowedUnits = [.hour, .minute]
return formatter
}()
Will produce:
01:30
Bottom line, if you really want to calculate minutes and seconds, feel free, but if it’s solely to create a string representation, let the DateComponentFormatter do this for you.
EDIT
I realize you wanted to know what did not work with your method.
It's a matter of rounding, try roundind hours before passing it to String(format:) :
func decimalHoursConv (hours : Double) -> (_hrs:String, mins:String) {
let remainder = hours.truncatingRemainder(dividingBy: 1) * 60
let mins = (String(format: "%.0f", remainder))
let hours = hours.rounded(.towardZero)
let hrs = (String(format: "%.0f", hours))
return (hrs, mins)
}
it gives :
var value = (450.0-185.0)/3
decimalHoursConv(hours: value/60) // (_hrs "1", mins "28")
value = (450.0-182.0)/3
decimalHoursConv(hours: value/60) // (_hrs "1", mins "29")
value = (450.0-181.0)/3
decimalHoursConv(hours: value/60) // (_hrs "1", mins "30")
value = (450.0-180.0)/3
decimalHoursConv(hours: value/60) // (_hrs "1", mins "30")
value = (450.0-179.0)/3
decimalHoursConv(hours: value/60) // (_hrs "1", mins "30")
value = (450.0-175.0)/3
decimalHoursConv(hours: value/60) // (_hrs "1", mins "32")
BUT Still
If you're using Swift you should use Measurement
func convertToHoursAndMinutes(_ value: Double) -> DateComponents {
let unitMeasurement = Measurement(value: value, unit: UnitDuration.minutes)
let hours = unitMeasurement.converted(to: .hours).value
let decimalPart = hours.truncatingRemainder(dividingBy: 1)
let decimalPartMeasurement = Measurement(value: decimalPart, unit: UnitDuration.hours)
let decimalPartMeasurementInMinutes = decimalPartMeasurement.converted(to: .minutes)
let minutes = decimalPartMeasurementInMinutes.value.rounded(.toNearestOrEven)
return DateComponents(hour: Int(hours), minute: Int(minutes))
}
usage :
var value = (450.0-185.0)/3 // 88.33333333333333
convertToHoursAndMinutes(value) // hour: 1 minute: 28 isLeapMonth: false
value = (450.0-182.0)/3 // 89.33333333333333
convertToHoursAndMinutes(value) // hour: 1 minute: 29 isLeapMonth: false
value = (450.0-181.0)/3 // 89.66666666666667
convertToHoursAndMinutes(value) // hour: 1 minute: 30 isLeapMonth: false
value = (450.0-180.0)/3 // 90
convertToHoursAndMinutes(value) // hour: 1 minute: 30 isLeapMonth: false
value = (450.0-179.0)/3 // 90.33333333333333
convertToHoursAndMinutes(value) // hour: 1 minute: 30 isLeapMonth: false
value = (450.0-175.0)/3 // 91.66666666666667
convertToHoursAndMinutes(value) // hour: 1 minute: 32 isLeapMonth: false
Note that you can always use a tuple instead of DateComponents if you prefer.
String formatter rounds up.
You can use .rounded(.down) on Doubles to round them down. (or with other rules you need)
let number = (179.0/60.0) // 2.983333333333333
String(format: "%.0f", number) // returns 3
number.rounded(.up) // returns 3
number.rounded(.down) // returns 2
First you should structure your data. Next you don't need to format your value as a Double if you are not gonna display fractions. So you can simply convert your double to integer.
struct FlightPlan {
let plannedStartFuel: Double
let minimumLandAllowance: Double
}
extension FlightPlan {
var mlaTime: (hours: Int, minutes: Int) {
let hours = (plannedStartFuel - minimumLandAllowance) / 180
return (Int(hours), Int(modf(hours).1 * 60))
}
}
And you should use DateComponentsFormatter when displaying time to the user:
extension Formatter {
static let time: DateComponentsFormatter = {
let formatter = DateComponentsFormatter()
formatter.calendar?.locale = .init(identifier: "en_US_POSIX")
formatter.unitsStyle = .brief
formatter.allowedUnits = [.hour,.minute]
return formatter
}()
}
extension FlightPlan {
var mlaTimeDescrition: String {
return "Flight Time To MLA = " + Formatter.time.string(from: .init(hour: mlaTime.hours, minute: mlaTime.minutes))!
}
}
let flightPlan = FlightPlan(plannedStartFuel: 450,
minimumLandAllowance: 180)
flightPlan.mlaTime // (hours 1, minutes 30)
flightPlan.mlaTime.hours // 1
flightPlan.mlaTime.minutes // 30
flightPlan.mlaTimeDescrition // "Flight Time To MLA = 1hr 30min"

Formula of Hijri date

What is the formula of converting "Time since epoch" stamp such as 1525249213 to Hijri date (Year - Month - Day)?
I know there would be one day inaccuracy which is OK for me.
The algorithm I found is to convert the Date to a Julian Date then convert the julian date to Hijri.
P.S. I can not remember where I found it. I am not responsible for any error or miss-accuracy or an consequence bla bla bla of using this code.
unsigned long gregorian_to_julian(const int gyear, const int gmonth, const int gday) {
if (gmonth < 3) {
gyear -= 1;
gmonth += 12;
}
auto a = int(gyear / 100.0f);
auto b = (gyear == 1582 && (gmonth > 10 || (gmonth == 10 && gday > 4)) ? -10 :
(gyear == 1582 && gmonth == 10 ? 0 :
(gyear < 1583 ? 0 : 2 - a + int(a / 4.0f))));
return int(365.25f * (gyear + 4716)) + int(30.6001f * (gmonth + 1)) + gday + b - 1524;
}
std::array<int,3> julian_to_hijri(const unsigned long julian_datestamp) {
std::array<int,3> result;
auto y = 10631.0f / 30.0f;
auto epoch_astro = 1948084;
auto shift1 = 8.01f / 60.0f;
auto z = julian_day - epoch_astro;
auto cyc = int(z / 10631.0f);
z = z - 10631 * cyc;
auto j = int((z - shift1) / y);
z = z - int(j * y + shift1);
result[0] = 30 * cyc + j; //Hijri Year
result[1]= int((z + 28.5001f) / 29.5f); //Hijri Month
if (result[1] == 13) {
result[1]= 12;
}
result[2] = z - int(29.5001f * result[1]- 29);// Hijri day
return result;
}
P.S. there will be +-1 one day error in the result Hijri date.

Calculate average pace

I need to convert a decimal hour in to hh:mm:ss to display as average pace for a walking app.
I have converted the time to decimal and I have calculated the pace in to decimal however I am unsure how to convert this to time.
My timeDecimal is:
let timeDecimal:Double = (hourSource + (minuteSource / 60) + (secondSource / 3600)) / distanceSource
which gives me something like 0.4375
0 = 0
.4375 * 60 = 26.25
.25 = * 60 = 15
I know the time should be 00:26:15 but not sure the formula to achieve this without splitting up the result and performing the multiplication multiple times.
Any help is appreciated.
let formatter = NSDateComponentsFormatter()
formatter.allowedUnits = [ .Hour, .Minute, .Second ]
formatter.unitsStyle = .Positional
formatter.zeroFormattingBehavior = .Pad
let string = formatter.stringFromTimeInterval(0.4375 * 3600)!
Result: 0:26:15.
Try
var mytime = timeDecimal * 60
var minutes = floor(mytime)
var seconds = (mytime - minutes) * 60
func timeStringFrom(time time: Int) -> String {
let HoursLeft = time/3600
let MinutesLeft = (time%3600)/60
let SecondsLeft = (((time%3600)%60)%60)
if HoursLeft == 0 {
return String(format:"%.2d:%.2d", MinutesLeft, SecondsLeft)
} else {
return String(format:"%2d:%.2d:%.2d", HoursLeft, MinutesLeft, SecondsLeft)
}
}
Note: I'll probably turn it into a generic function soon

Basic Adding - Expression was too complex error (Swift)

Trying to add some simple numbers together. Get the "Expression was too complex to be solved in a reasonable time..." error on the final line. Why? Surely it can't come much simpler?
let year = calendar.component(.CalendarUnitYear, fromDate: inputGregorianDate)
let month = calendar.component(.CalendarUnitMonth, fromDate: inputGregorianDate)
let day = calendar.component(.CalendarUnitDay, fromDate: inputGregorianDate)
// Conversion Calulation
let AGR = year/100
let BGR = AGR/4
let CGR = 2 - AGR + BGR
var EGR = 0.00
if (month <= 2 ) {
EGR = 365.25 * Double(year + 4716)
} else {
EGR = 365.25 * Double(year + 4716);
}
let FGR = 30.6001 * Double(month + 1);
let dateJulian = Double(CGR + day + EGR + FGR - 1524.5)
// Conversion Calulation
let AGR = Double(year) / 100
let BGR = AGR / 4.0
let CGR = 2.0 - AGR + BGR
var EGR = 0.0
// this conditional doesn't make any sense
if (month <= 2 ) {
EGR = 365.25 * Double(year + 4716)
} else {
EGR = 365.25 * Double(year + 4716)
}
let FGR = 30.6001 * Double(month + 1)
let dateJulian = CGR + Double(day) + EGR + FGR - 1524.5

How to calculate the time difference between 2 date time values

I am trying to calculate the time difference between 2 date time strings.
I have 2 inputs where the input string is something like this "1:00 PM" and the second one "3:15 PM". I want to know the time difference. So for the above example I want to display 3.15
What I have done:
Converted the time to a 24 hours format. So "1:00 PM" becomes "13:00:00"
Appended the new time to a date like so: new Date("1970-1-1 13:00:00")
Calculated the difference like so:
Code:
var total = Math.round(((new Date("1970-1-1 " + end_time) -
new Date("1970-1-1 " + start_time) ) / 1000 / 3600) , 2 )
But the total is always returning integers and not decimals, so the difference between "1:00 PM" and "3:15 PM" is 2 not 2.15.
I have also tried this (using jQuery, but that is irrelevant):
$('#to_ad,#from_ad').change(function(){
$('#total_ad').val( getDiffTime() );
});
function fixTimeString(time){
var hours = Number(time.match(/^(\d+)/)[1]);
var minutes = Number(time.match(/:(\d+)/)[1]);
var AMPM = time.match(/\s(.*)$/)[1];
if(AMPM == "PM" && hours<12) hours = hours+12;
if(AMPM == "AM" && hours==12) hours = hours-12;
var sHours = hours.toString();
var sMinutes = minutes.toString();
if(hours<10) sHours = "0" + sHours;
if(minutes<10) sMinutes = "0" + sMinutes;
return sHours + ':' + sMinutes + ':00';
}
function getDiffTime(){
var start_time = fixTimeString($('#from_ad').val());
var end_time = fixTimeString($('#to_ad').val());
var start = new Date("1970-1-1 " + end_time).getTime(),
end = new Date("1970-1-1 " + start_time).getTime();
return parseInt(((start - end) / 1000 / 3600, 10)*100) / 100;
}
But the total_ad input is displaying only integer values.
How can I fix this problem?
Math.round rounds to the nearest integer, multiply and divide instead
var start = new Date("1970-1-1 " + start_time).getTime(),
end = new Date("1970-1-1 " + end_time).getTime();
var total = (parseInt(((start-end) / 1000 / 3600)*100, 10)) / 100;
FIDDLE
When you take the time 15:15:00 and subtract 13:00:00, you're left with 2.15 hours, not 3.15, and this example would return 2.15 even without making sure there is only two decimals, but for other times that might not be the case.
You could also use toFixed(2), but that would leave you with 3.00 and not 3 etc.
This is how I calculate it:
calculateDiff();
function calculateDiff(){
_start = "7:00 AM";
_end = "1:00 PM";
_start_time = parseAMDate(_start);
_end_time = parseAMDate(_end);
if (_end_time < _start_time){
_end_time = parseAMDate(_end,1);
}
var difference= _end_time - _start_time;
var hours = Math.floor(difference / 36e5),
minutes = Math.floor(difference % 36e5 / 60000);
if (parseInt(hours) >= 0 ){
if (minutes == 0){
minutes = "00";
}
alert(hours+":"+minutes);
}
}
function parseAMDate(input, next_day) {
var dateReg = /(\d{1,2}):(\d{2})\s*(AM|PM)/;
var hour, minute, result = dateReg.exec(input);
if (result) {
hour = +result[1];
minute = +result[2];
if (result[3] === 'PM' && hour !== 12) {
hour += 12;
}
}
if (!next_day) {
return new Date(1970, 01, 01, hour, minute).getTime();
}else{
return new Date(1970, 01, 02, hour, minute).getTime();
}
}