Trying to replace moment.js in my Angular application with Luxon to reduce bundle size.
I have come across a case where the two libraries produce a different output, and I am not sure why.
moment.js produces a date that is one hour ahead.
const activeToDateTimeString = '2014-08-06T13:07:04';
let foo1 = moment(activeToDateTimeString).utcOffset(-5, true);
let foo2 = DateTime.fromISO(activeToDateTimeString, {zone: 'America/New_York'}).setZone('America/New_York', { keepLocalTime: true });
let foo3 = DateTime.fromJSDate(new Date(activeToDateTimeString)).setZone('America/New_York', { keepLocalTime: true });
let foo4 = DateTime.fromISO(activeToDateTimeString).setZone('America/New_York', { keepLocalTime: true });
console.log(foo1.toDate());
console.log(foo2.toJSDate());
console.log(foo3.toJSDate());
console.log(foo4.toJSDate());
Output:
Wed Aug 06 2014 14:07:04 GMT-0400 (Eastern Daylight Time)
Wed Aug 06 2014 13:07:04 GMT-0400 (Eastern Daylight Time)
Wed Aug 06 2014 13:07:04 GMT-0400 (Eastern Daylight Time)
Wed Aug 06 2014 13:07:04 GMT-0400 (Eastern Daylight Time)
Why does moment.js produce a different output in this case?
let foo1 = moment(activeToDateTimeString).utcOffset(-4, true);
This would correct your code, but as you're moving to Luxon the daylight time changes won't effect you in the future.
Right now (19 mar 2020) New York is 4 hours behind UTC as from the 8th March 2020 it entered Eastern Daylight Time from Eastern Standard Time.
If New York was in Eastern Standard Time at the moment your code would output the same times.
In a Vuejs app, I currently have a button that is usable once a day. After it is clicked once, it is disabled until the following day. This works fine locally, but on heroku, the comparison does not seem to work.
Here is y date computed value in the vue component which returns true if the Act was created after 00:00 on the current date:
computed: {
...
actedToday() {
if (!!this.$store.getters.lastAct) {
let now = new Date();
console.log('this is now in actedToday computed: ', now);
let lastActDate = new Date(this.$store.getters.lastAct.created_at);
console.log('this is last act date in computed actedToday', this.$store.getters.lastAct.created_at);
console.log('was last Act today? ', lastActDate.getTime() > now.setHours(0,0,0,0));
return lastActDate.getTime() > now.setHours(0,0,0,0)
}
}
},
Here is what the console.log returns locally:
this is now in actedToday computed: Fri Oct 04 2019 15:20:24 GMT-0400 (Eastern Daylight Time)
ActButton.vue?0bb7:31 this is last act date in computed actedToday 2019-10-04T19:20:23.901Z
ActButton.vue?0bb7:32 was last Act today? true
And here is the analogous logs from the heroku app:
this is now in actedToday computed: Fri Oct 04 2019 15:21:18 GMT-0400 (Eastern Daylight Time)
ActButton.vue:31 this is last act date in computed actedToday 2019-10-04T03:30:22.266Z
ActButton.vue:32 was last Act today? false
In the first example, the comparison works as expected. In the second, although both dates are on the same day, the comparison returns false.
Your problem occurs due to different timezones. Your lastActDate is in Zulu-time (UTC, note the Z at the end) but your actedToday is in EDT. Using setHours(0,0,0,0) will give you the start of the day, but in the same timezone. Thus you have the following values:
//locally
now = Fri Oct 04 2019 15:20:24 GMT-0400 (Eastern Daylight Time)
now.setHours(0,0,0,0) = Fri Oct 04 2019 00:00:00 GMT-0400 (Eastern Daylight Time)
lastActDate = 2019-10-04T19:20:23.901Z = Fri Oct 04 2019 15:20:23.901 GMT-0400 (Eastern Daylight Time)
//heroku
now = Fri Oct 04 2019 15:21:18 GMT-0400 (Eastern Daylight Time)
now.setHours(0,0,0,0) = Fri Oct 04 2019 00:00:00 GMT-0400 (Eastern Daylight Time)
lastActDate = 2019-10-04T03:30:22.266Z = Fri Oct 03 2019 23:30:22.266 GMT-0400 (Eastern Daylight Time)
Thus heroku is right and your last action has not been "today". You should consider to use the same timezone in all of your dates.
I am getting a weird issue in SSRS. Say I have a dataset with the record createdon date as shown below.
createdon
12/7/2018 5:11 PM
12/11/2018 6:10 PM
12/12/2018 8:07 PM
12/14/2018 1:24 PM
12/14/2018 2:10 PM
12/14/2018 4:24 PM
12/4/2018 9:57 PM
12/6/2018 4:25 PM
12/6/2018 4:30 PM
How can I get the Max(creation) date? If I do max, I am getting 12/7/2018 5:11 PM instead of 12/14/2018 4:24 PM.
This should work:
Max(CDate(Fields!Createdon.Value))
I'm implementing a sign up facility which sends a link with a token in it - the token is valid for 1 hour. So in the email (let's say it is 14:20 now) I want to say:
You must click this link by 15:30
The audience for this site will be in Ireland / UK, USA / Canada and perhaps some in Europe - so I wanted to list the expiry time in several time zones that these (non technical) people will understand.
So this is what I came up with
Click by:
Ireland/UK > 25 Apr 2018 13:59
CET (Berlin) > 25 Apr 2018 14:59
Pacific (Los Angeles) > 25 Apr 2018 05:59
Mountain (Denver) > 25 Apr 2018 06:59
Central (Chicago) > 25 Apr 2018 07:59
Eastern (New York) > 25 Apr 2018 08:59
Now, I understand that Denver is currently MDT (and MST in the winter), but here in Ireland, we are now in IST (UTC + 1) or GMT in the winter/fall - but if you ask a random person what timezone are we in, at best you will get GMT as a response all year round. So, I list the time there as a generic 'Mountain' and give a sample city.
How is this approach for people in USA / Canada?
My code is below and here is a live link
<?php
$exipry = 60*60 + time();
$now_obj = new DateTime(date("Y-m-d H:i:s", $exipry));
$now_obj->setTimezone(new DateTimeZone('Europe/Dublin'));
$now_hour_from_IRELAND_datetime = $now_obj->format('d M Y H:i');
$now_obj->setTimezone(new DateTimeZone('Europe/Berlin'));
$now_hour_from_CET_datetime = $now_obj->format('d M Y H:i');
$now_obj->setTimezone(new DateTimeZone('America/Los_Angeles'));
$now_hour_from_pacific_datetime = $now_obj->format('d M Y H:i');
$now_obj->setTimezone(new DateTimeZone('America/Denver'));
$now_hour_from_mountain_datetime = $now_obj->format('d M Y H:i');
$now_obj->setTimezone(new DateTimeZone('America/Chicago'));
$now_hour_from_central_datetime = $now_obj->format('d M Y H:i');
$now_obj->setTimezone(new DateTimeZone('America/New_York'));
$now_hour_from_eastern_datetime = $now_obj->format('d M Y H:i');
print("<h1>1 hour from now is:</h1>");
print("Ireland/UK > $now_hour_from_IRELAND_datetime<p>");
print("CET (Berlin) > $now_hour_from_CET_datetime<p>");
print("Pacific (Los Angeles) > $now_hour_from_pacific_datetime<p>");
print("Mountain (Denver) > $now_hour_from_mountain_datetime<p>");
print("Central (Chicago) > $now_hour_from_central_datetime<p>");
print("Eastern (New York) > $now_hour_from_eastern_datetime<p>");
?>
Looks correct to me.
Be sure to test it for 'Asia/Kolkata' too. That's a good test because its time zone offset is on a half-hour.
Ditto for 'America/Phoenix' because they stay on standard time all year.
Usually apps like this ask each user to provide a timezone name during onboarding. (But many users don't bother)
In the US when we want to specify a timezone in a way where it doesn't have to change between summer and winter, we say "Eastern Time", "Central Time", "Mountain Time", "Pacific Time," and Hawaii and Alaska time. The Canadians also have "Atlantic Time" ('America/Halifax'). In Arizona ('America/Phoenix') they say 'Arizona Time'.
I need help applying settings across a calendar year. My users are entering numerical targets into a database according to the season in a calendar. Think, apple cider will sell higher during the fall (September through November) and less during the rest of the year (December through August). However, apple juice sells evenly throughout the year.
To simplify data entry for my users, they enter a target sales number along with the month that number will start for each product.
For example, the data in the database will look like this (There are a max of two targets for any product):
Apple Cider - September - 5,000 gallons
Apple Cider - December - 1,000 gallons
Apple Juice - September - 3,000 gallons
I also have our fiscal calendar in a database table, so I know what fiscal year, month, number of weeks in the month, etc. are associated with any day.
I need to apply this data to a report, but I need data for every month in the year, not just what the user has entered.
I'm having trouble using LINQ to join to my fiscal calendar to create an exploded view of the data? How can I start with a list of all months in the year, for each product, place the targets in the calendar, then fill in the blanks. For example for Apple Cider using the example above
January
February
March
April
May
June
July
August
September - 5,000 gallonws
October
November
December - 1,000 gallons
Apple Cider - September - 5,000 gallons
Apple Cider - October - 5,000 gallons
Apple Cider - November - 5,000 gallons
Apple Cider - December - 1,000 gallons
Apple Cider - January - 1,000 gallons
Apple Cider - February- 1,000 gallons
Apple Cider - March - 1,000 gallons
Apple Cider - April- 1,000 gallons
Apple Cider - May - 1,000 gallons
Apple Cider - June - 1,000 gallons
Apple Cider - July - 1,000 gallons
Apple Cider - August - 1,000 gallons
Apple Juice - September - 3,000 gallons
Apple Juice - October - 3,000 gallons
Apple Juice - November - 3,000 gallons
Apple Juice - December - 3,000 gallons
Apple Juice - January - 3,000 gallons
Apple Juice - February - 3,000 gallons
Apple Juice - March - 3,000 gallons
Apple Juice - April - 3,000 gallons
Apple Juice - May - 3,000 gallons
Apple Juice - June - 3,000 gallons
Apple Juice - July - 3,000 gallons
Apple Juice - August - 3,000 gallons
I'm not sure how much help LINQ would be in this scenario.
You can achieve the required transformation relatively simply with a for loop:
' Sample data using anonymous types
Dim entries() =
{New With {.Name = "Apple Cider", .Year = 2012, .Month = 9, .Quantity = 5000},
New With {.Name = "Apple Cider", .Year = 2012, .Month = 12, .Quantity = 1000},
New With {.Name = "Apple Juice", .Year = 2013, .Month = 9, .Quantity = 3000}}
' Dictionary keyed by date
Dim dict = entries.ToDictionary( _
Function(entry) New DateTime(entry.Year, entry.Month, 1))
' Current is first entry
Dim currentEntry = entries(0)
Dim epoch = New DateTime(currentEntry.Year, currentEntry.Month, 1)
' Iterate over 24 months
For i = 0 To 23
Dim currentMonth = epoch.AddMonths(i)
' Update current based on current month
If dict.ContainsKey(currentMonth) Then
currentEntry = dict(currentMonth)
End If
' Write data
Console.WriteLine("{0} - {1} - {2} gallons",
currentEntry.Name,
MonthName(currentMonth.Month),
currentEntry.Quantity)
Next
To do this with Linq use Range() (in cases where something can be done in a loop often range can be substituted.)
Here is an example using Enumerable.Range and #PhillipTrelford's example data:
Sub Main
Dim entries() = {New With {.Name = "Apple Cider", .Year = 2012, .Month = 9, .Quantity = 5000}, _
New With {.Name = "Apple Cider", .Year = 2012, .Month = 12, .Quantity = 1000}, _
New With {.Name = "Apple Juice", .Year = 2013, .Month = 9, .Quantity = 3000}}
Dim dict = entries.ToDictionary( Function(entry) New DateTime(entry.Year, entry.Month, 1))
Dim startDate as DateTime = New DateTime(2012,9,1)
Dim curDefault = New With {.Name = "", .Quantity = 0}
Dim result = Enumerable.Range(0, 24).Select(Function(x)
Dim thisdate = startDate.AddMonths(x)
If dict.ContainsKey(thisdate) Then
curDefault.Name = dict(thisdate).Name
curDefault.Quantity = dict(thisdate).Quantity
End If
Return String.Format("{0} - {1} - {2} gallons",curDefault.Name,thisdate.ToString("MMMM"),curDefault.Quantity)
End Function)
result.Dump
End Sub
This code runs just fine and give expected results using linqpad (see linqpad.com)
Apple Cider - September - 5000 gallons
Apple Cider - October - 5000 gallons
Apple Cider - November - 5000 gallons
Apple Cider - December - 1000 gallons
Apple Cider - January - 1000 gallons
Apple Cider - February - 1000 gallons
Apple Cider - March - 1000 gallons
Apple Cider - April - 1000 gallons
Apple Cider - May - 1000 gallons
Apple Cider - June - 1000 gallons
Apple Cider - July - 1000 gallons
Apple Cider - August - 1000 gallons
Apple Juice - September - 3000 gallons
Apple Juice - October - 3000 gallons
Apple Juice - November - 3000 gallons
Apple Juice - December - 3000 gallons
Apple Juice - January - 3000 gallons
Apple Juice - February - 3000 gallons
Apple Juice - March - 3000 gallons
Apple Juice - April - 3000 gallons
Apple Juice - May - 3000 gallons
Apple Juice - June - 3000 gallons
Apple Juice - July - 3000 gallons
Apple Juice - August - 3000 gallons