背景: 私が働いている会社には、イベントに使用するカスタム ContentType (カレンダー リスト アイテムから継承されない) を持つ通常の SharePoint リストがあります。次に、カレンダー ビューを使用してこれらを表示します。十分に単純に思えます。ユーザーが追加するイベントのタイムゾーン (地域の設定とは異なる) を選択できるようにし、情報を sharepoint に追加して、世界中の各ユーザーに正しい時刻が表示されるようにする必要があります (もちろん、地域設定に基づいています)。SystemTimeZones のルックアップに使用されるリストを SharePoint に追加しました (基本的には、TimeZoneInfo.GetSystemTimeZones() の SharePoint リスト表現)。
SPList timeZonesList = thisWeb.Lists.TryGetList("SystemTimeZones");
if(timeZonesList == null)
{
string title = "SystemTimeZones";
string description = "SharePoint List representation of TimeZoneInfo.GetSystemTimeZones() used for lookup.";
Guid newListId = thisWeb.Lists.Add(title, description, SPListTemplateType.GenericList);
timeZonesList = thisWeb.Lists.GetList(newListId, true);
timeZonesList.Fields.Add("SystemTimeZoneId", SPFieldType.Text, true);
timeZonesList.Fields.Add("SystemTimeZoneName", SPFieldType.Text, true);
SPView defaultTimeZonesView = timeZonesList.DefaultView;
defaultTimeZonesView.ViewFields.Add("SystemTimeZoneId");
defaultTimeZonesView.ViewFields.Add("SystemTimeZoneName");
defaultTimeZonesView.Update();
foreach (TimeZoneInfo timeZone in TimeZoneInfo.GetSystemTimeZones())
{
SPListItem temp = timeZonesList.AddItem();
temp["SystemTimeZoneId"] = timeZone.Id;
temp["SystemTimeZoneName"] = timeZone.DisplayName;
temp.Update();
}
}
このリストのカスタム追加フォームと編集フォームで、EventTimeZone のルックアップ アイテムにこのリストを使用しています。フォームは、SharePoint Designer が作成するもの (SharePoint:FormField を使用しているという点で) の直接のコピーであり、コード ビハインドが必要だった Visual Studio 内にあるだけです。ユーザーが地域のタイムゾーンでイベントを表示できるようにしたかったのですが、編集するときに、入力したタイムゾーンで表示したかったのです。(つまり、私の地域のタイムゾーンは中部なので、山の会議を見ると午前 10 時から 11 時と表示されますが、同じ会議を編集すると午前 9 時から 10 時と表示されます)。したがって、編集のページ読み込み時に時間を調整します。
SPListItem thisEvent = eventsList.GetItemById(savebutton1.ItemId);
if (thisEvent != null)
{
bool isAllDayEvent = false;
if (thisEvent["fAllDayEvent"] != null)
{
isAllDayEvent = (bool)thisEvent["fAllDayEvent"];
}
if (!isAllDayEvent)
{
SPFieldLookupValue lookupValue = new SPFieldLookupValue(thisEvent["Event Time Zone"].ToString());
TimeZoneInfo eventTimeZone = GetEventTimeZoneByListItemId(lookupValue.LookupId, rootWeb);
SPTimeZone regionalTimeZone = GetRegionalTimeZone(rootWeb);
DateTime regionalStartDateTime = Convert.ToDateTime(thisEvent["StartDate"]);
DateTime originalStartDateTime = TimeZoneInfo.ConvertTimeFromUtc(regionalTimeZone.LocalTimeToUTC(regionalStartDateTime), eventTimeZone);
ff3.ListItemFieldValue = originalStartDateTime;
DateTime regionalEndDateTime = Convert.ToDateTime(thisEvent["EndDate"]);
DateTime originalEndDateTime = TimeZoneInfo.ConvertTimeFromUtc(regionalTimeZone.LocalTimeToUTC(regionalEndDateTime), eventTimeZone);
ff4.ListItemFieldValue = originalEndDateTime;
}
else
{
// for some reason with all day events, sharepoint saves them
// as the previous day 6pm. but when they show up to any user
// they will show as 12am to 1159pm and show up correctly on the calendar
// HOWEVER, when it comes to edit, the start date isn't corrected on the
// form, so continuing to save without fixing it will continue to decrease
// the start date/time by one day
DateTime regionalStartDateTime = Convert.ToDateTime(thisEvent["StartDate"]);
ff3.ListItemFieldValue = regionalStartDateTime.AddDays(1);
}
終日のイベントは奇妙でしたが、テストケースを書き、何が起こったのかを確認するだけで機能させることができました (私のコメントからわかるように)。
次に、リスト イベント レシーバーの ItemAdded と ItemUpdated を結び付けて時間を「修正」します。これは、SharePoint がユーザーが選択したタイムゾーンではなく、ユーザーの地域設定に基づいて時間を保存するためです。(もちろん、私はSharePointに少し慣れていません.C#ではないので、これを非常に複雑にしているかもしれませんが、オンラインで少しドキュメントを細かくすることができました). 最後に、私は設定を終了します:
addedItem["StartDate"] = regionalTimeZone.UTCToLocalTime(correctedEventStart.ToUniversalTime());
addedItem["EndDate"] = regionalTimeZone.UTCToLocalTime(correctedEventEnd.ToUniversalTime()); TADA!! It saves and display perfectly! I was so excited! Until... I tried to save a recurring event. All of my recurring events save wonderfully, it's not the recurring part that's messed up. For some reason, after I change the StartDate and EndDate on a recurring event and call addedItem.Update() it is recalculating the "Duration" as if it is a single even instead of a recurring event. Example: I have an event that happens for a week daily from 9-10. When I first enter ItemAdded my Duration is 3600 (1 hour) as it should be bc Duration is treated differently for recurring events. However after I adjust the times and call Update() the duration spans the entire week :( If I manually set the Duration:
if (isRecurrence)
{
addedItem["Duration"] = (correctedEventEnd.TimeOfDay - correctedEventStart.TimeOfDay).TotalSeconds;
}
Update() でリセットされます。そのため、定期的なアイテムをカレンダー ビューで表示すると、アイテムは 1 日に 1 回表示されるのではなく、1 週間にわたって表示されます。
私はこれを理解しようとして髪を引っ張っただけです。どんなガイダンスも素晴らしいでしょう。Duration が計算フィールドであることは理解していますが、 listItem.Update() を呼び出すと、実際に定期的なイベントとして適切にマークされているという事実が無視され、Duration が正しく計算されない理由がわかりません。これは正直なところ、SP 2010 のバグのようです。
前もって感謝します!
**
編集:以下のコメントの後の追加情報...
** この SharePoint 環境には、太平洋時間のサーバーと、すべての米国タイムゾーン、ロンドン、東京、アブダビなどのユーザーがいます。あるタイムゾーンのユーザーは、他のタイムゾーンでイベントを作成できる必要があります。ユーザーのプロファイルには (いずれにせよ) どのタイムゾーンですべてを表示したいかがわからないため、マスター ページにコードを追加して、ローカル コンピューターのタイムゾーンを確認し、それに応じて地域設定を常に設定します。
例: 私はナッシュビルにいて、LA で開催されるイベントを作成したいと考えています。
ItemAdded のデータは、StartDate が午前 9 時に入力したことを示しています。だから私はそれの最後にPSTを持つ日付を作成しています:
DateTime correctedEventStart = DateTime.Parse(addedItem["StartDate"] + " " + eventTimeZone.GetUtcOffset(DateTime.UtcNow).Hours + ":" + eventTimeZone.GetUtcOffset(DateTime.UtcNow).Minutes);
DateTime correctedEventEnd = DateTime.Parse(addedItem["EndDate"] + " " + eventTimeZone.GetUtcOffset(DateTime.UtcNow).Hours + ":" + eventTimeZone.GetUtcOffset(DateTime.UtcNow).Minutes);
次に、SharePoint を「だます」ために、その PST 時間をユーザーの地域時間に変換します (ユーザーは地域設定について何も知らなくてもよく、考える必要もありません)。したがって、PST の午前 9 時は CST の午前 7 時です (私の地域の設定であるため、SharePoint が期待する時刻です)。正しい時刻とタイムゾーンからユーザーの地域のタイムゾーンへの変換は次のとおりです。
addedItem["StartDate"] = regionalTimeZone.UTCToLocalTime(correctedEventStart.ToUniversalTime());
addedItem["EndDate"] = regionalTimeZone.UTCToLocalTime(correctedEventEnd.ToUniversalTime());
これが私の世界の外の誰にとっても意味があるかどうかはわかりません。しかし、SharePoint は明らかに、時刻がユーザーの地域 (または Web の) タイムゾーンにあることを期待しています。それは私の単体テストから明らかです。中央時間のユーザーがカスタム リストで太平洋時間の午前 9 時から 10 時まで会議を作成できるようにする OOB の方法があれば、それを使用できるようにしたいと思います。しかし、私は何も見つけることができませんでした。
繰り返しますが、これはすべてうまく機能します...定期的なイベントに到達するまでは。そして、実際には、カレンダー ビューでそのイベントを表示しようとするまで、定期的なイベントに対して機能します。次に、次のようになります。
"Recurring 8" が想定どおりに、毎日 2 回繰り返されていることに注意してください。ただし、繰り返しの「スパン」または「期間」は 1 時間ではなく 2 日間です。「繰り返し15」が正しく表示されます。デバッグへの出力時の 2 つのフィールド値の唯一の違いは、「期間」フィールドです。繰り返し 8 は ItemAdded で開始日と終了日が更新され、繰り返し 15 は ItemAdded を通過しましたが、ListItem.Update() はコメントアウトされました。ドキュメントによると、SharePoint は、単一のアイテムとは異なる繰り返しアイテムの期間を計算することになっています。オブジェクト モデルを使用して開始日と終了日が変更されるという事実は、それを否定するものではありません。